home *** CD-ROM | disk | FTP | other *** search
/ Magnum One / Magnum One (Mid-American Digital) (Disc Manufacturing).iso / d12 / v9n20.arc / PCSORT.ASM < prev    next >
Assembly Source File  |  1990-10-29  |  105KB  |  3,311 lines

  1. ;--------------------------------------------------;
  2. ;  PCSORT * PC Magazine * Michael J. Mefford       ;
  3. ;                                                  ;
  4. ;  Text file column sort utility.                  ;
  5. ;--------------------------------------------------;
  6.  
  7. _TEXT          SEGMENT PUBLIC 'CODE'
  8.                ASSUME  CS:_TEXT,DS:_TEXT,ES:_TEXT,SS:_TEXT
  9.                ORG     100H
  10. START:         JMP     MAIN
  11.  
  12. ;              DATA AREA
  13. ;              ---------
  14. COLOR_ATTRIBS  STRUC
  15. B              DB      71H                     ;Blue on lt. gray
  16. W              DB      17H                     ;Lt. gray on blue
  17. C              DB      31H                     ;Blue on cyan
  18. COLOR_ATTRIBS  ENDS
  19.  
  20. COLOR          COLOR_ATTRIBS  <>
  21.  
  22. COLOR_ATTR     COLOR_ATTRIBS  <>
  23. MONO_ATTR      COLOR_ATTRIBS  <70H, 07H, 70H>
  24.  
  25. BORDER_FLAG    DB      0                       ; =1 to disable.
  26.  
  27. SIGNATURE      DB      CR,SPACE,SPACE,SPACE,CR,LF
  28. COPYRIGHT      DB      "PCSORT 1.0 (c) 1990 Ziff Communications Co. ",CR,LF
  29. PROGRAMMER     DB      "PC Magazine ",BOX," Michael J. Mefford",LF
  30. CRLF           DB      CR,LF
  31.  
  32. SYNTAX LABEL BYTE
  33. DB      "Syntax:  PCSORT [filename] [options]",CR,LF,LF
  34. DB      "/C      Case sensitive sort; default=Case insensitive",CR,LF
  35. DB      "/S n    n=size of record in lines (1-9); default=1",CR,LF
  36. DB      "/P n    n=sort priority (1-9); default=1",CR,LF
  37. DB      "/R      sort current priority in reverse order",CR,LF
  38. DB      "        default order is ascending",CR,LF
  39. DB      "/N      Numeric sort current priority; default=Alphanumeric",CR,LF
  40. DB      "/L[n]   Line sort; n=record sort line (1-9); default=1",CR,LF
  41. DB      "        default sort is a line sort",CR,LF
  42. DB      "/nn [xx [y]]   Block or column sort",CR,LF
  43. DB      "        nn=start column; xx=width; y=sort line (1-9)",CR,LF
  44. DB      "        defaults: nn=1; xx=start column to end of line; y=1",CR,LF
  45. DB      "/W [+|-] n   Word sort; n=word count",CR,LF
  46. DB      "        minus is count from end of record; default is plus 1",CR,LF
  47. DB      "   PcSort can be used as a filter.  For example,",CR,LF
  48. DB      "      DIR | PCSORT /P1 W2 /P2 W1 > EXAMPLE",CR,LF
  49. DB      "   creates an EXAMPLE file of a DIR sorted by extension and name.",CR,LF
  50. DB      "$",CTRL_Z
  51.  
  52. TAB            EQU     9
  53. CR             EQU     13
  54. LF             EQU     10
  55. CTRL_Z         EQU     26
  56. SPACE          EQU     32
  57. BOX            EQU     254
  58. FF             EQU     12
  59. SHIFT_KEYS     EQU     3
  60. ESC_SCAN       EQU     1
  61. Y_SCAN         EQU     15H
  62. N_SCAN         EQU     31H
  63. F1_SCAN        EQU     3BH
  64. F2_SCAN        EQU     3CH
  65. F3_SCAN        EQU     3DH
  66. F4_SCAN        EQU     3EH
  67. F5_SCAN        EQU     3FH
  68. F6_SCAN        EQU     40H
  69. F7_SCAN        EQU     41H
  70. F8_SCAN        EQU     42H
  71. F9_SCAN        EQU     43H
  72. F10_SCAN       EQU     44H
  73. KB_FLAG        EQU     17H
  74. UP_SCAN        EQU     48H
  75. DOWN_SCAN      EQU     50H
  76. LEFT_SCAN      EQU     4BH
  77. RIGHT_SCAN     EQU     4DH
  78. PGUP_SCAN      EQU     49H
  79. PGDN_SCAN      EQU     51H
  80. BS_SCAN        EQU     0EH
  81. DEL_SCAN       EQU     53H
  82. HOME_SCAN      EQU     47H
  83. END_SCAN       EQU     4FH
  84. ENTER_SCAN     EQU     1CH
  85. TAB_SCAN       EQU     0FH
  86. CTRL_HOME_SCAN EQU     77H
  87. CTRL_END_SCAN  EQU     75H
  88. SHIFT_F5       EQU     58H
  89. SHIFT_F6       EQU     59H
  90. SHIFT_F9       EQU     5CH
  91. SHIFT_F10      EQU     5DH
  92. ALT_F1         EQU     68H
  93.  
  94. COMMA          EQU     ","
  95. DECIMAL_POINT  EQU     "."
  96. PLUS_SIGN      EQU     "+"
  97. MINUS_SIGN     EQU     "-"
  98. NOTE           EQU     1046                    ; C
  99.  
  100. SCREEN_COLOR   DB      ?
  101.  
  102. CRT_MODE       EQU     49H
  103. CRT_COLS       EQU     4AH
  104. CRT_ROWS       EQU     84H
  105. COLUMNS        DW      ?
  106. CRT_WIDTH      DW      ?
  107. CRT_START      DW      ?
  108. STATUS_REG     DW      3BAH
  109. VIDEO_SEG      DW      0B000H
  110. ROWS           DB      24
  111. LISTING_LEN    DW      ?
  112.  
  113. SWITCH_CHARS    DB     "PRL+"
  114.                 DB     "WSNC"
  115. SWITCH_LEN      EQU    $ - SWITCH_CHARS
  116.  
  117. SWITCH_DISPATCH DW     SW_PRIORITY, SW_DIRECTION, SW_LINE,    SW_BLOCK
  118.                 DW     SW_WORD,     SW_RECORDS,   SW_NUMERIC, SW_CASE
  119.  
  120. CASE           DB      5FH    ;Capitalize; =FFh if case sensitive.
  121. JB_CODE        EQU     72H
  122. JA_CODE        EQU     77H
  123.  
  124. STDIN_FLAG     DB      1      ; =1 if redirection of input.
  125. MODIFY_FLAG    DB      0      ; =1 if file modified.
  126.  
  127. INDEX_SEG      DW      ?
  128. TEXT_SEG       DW      ?
  129. MEM_TOP_OFF    DW      ?
  130. MEM_TOP_SEG    DW      ?
  131.  
  132. FILENAME       DW      ?
  133. FILE_CURSOR    DW      ?
  134. EOF_SEG        DW      ?
  135. EOF_OFF        DW      ?
  136.  
  137. LINE_MAX       EQU     255
  138. LAST_LINE      DW      ?                       ;INDEX offset.
  139. TOP_LINE       DW      0                       ;INDEX offset.
  140. START_COLUMN   DW      0
  141. CURSOR_ROW     DB      ?
  142. CURSOR_COLUMN  DB      ?
  143. DISPLAY_COLUMN DW      ?
  144. DISPLAY_TEXT   DW      ?
  145. LONGEST_LINE   DW      ?                       ;Length of longest text line.
  146.  
  147. MARK_INDEX     DW      ?                       ;INDEX offset.
  148. MARK_LEFT      DW      ?                       ;Display column.
  149. MARK_RIGHT     DW      ?
  150.  
  151. INDEX_SIZE     EQU     1000H                ;64K / 16
  152. READ_SIZE      EQU     8000H                ;32K
  153.  
  154. INDEX_REC STRUC
  155. OFF_PTR        DW      ?
  156. SEG_PTR        DW      ?
  157. TEXT_LEN       DW      ?        ;Excluding line terminator (CR and/or LF)
  158. LINE_LEN       DW      ?        ;Including line terminator
  159. INDEX_REC ENDS
  160.  
  161.  
  162. LINES_PER_REC  DB      0
  163. INDEX_PER_REC  DW      SIZE INDEX_REC
  164. CURRENT_KEY    DB      0
  165.  
  166. ASCEND         EQU     0
  167. DESCEND        EQU     1
  168.  
  169. ALPHA_TYPE     EQU     0
  170. NUMERIC_TYPE   EQU     1
  171.  
  172. BLOCK_TYPE     EQU     0
  173. WORD_TYPE      EQU     1
  174. NONE_TYPE      EQU     2
  175. LINE_TYPE      EQU     3
  176.  
  177. INACTIVE       EQU     -1
  178.  
  179. LINES_REC_MAX  EQU     9
  180. KEY_MAX        EQU     9
  181.  
  182. SORT_KEY STRUC
  183. SORT_DIRECTION   DB    ASCEND
  184. KEY_TYPE         DB    ALPHA_TYPE
  185. KEY_FIELD        DB    LINE_TYPE
  186. BLOCK_INDEX      DW    0
  187. BLOCK_BEG        DW    INACTIVE
  188. BLOCK_LEN        DW    LINE_MAX
  189. WORD_POS         DB    1
  190. LINE_INDEX       DW    0
  191. SORT_KEY ENDS
  192.  
  193. KEYS           SORT_KEY <>
  194. OTHER_KEYS     SORT_KEY KEY_MAX-1 DUP (<,,NONE_TYPE,,,,>)
  195.  
  196. ALPHANUMERIC   DB      "Alphanumeric",0
  197. NUMERIC        DB      "Numeric     ",0
  198. ASCENDING      DB      "Ascending ",0
  199. DESCENDING     DB      "Descending",0
  200. BLOCK_MSG      DB      "Block",0
  201. WORD_MSG       DB      "Word ",0
  202. NONE_MSG       DB      "None ",0
  203. LINE_MSG       DB      "Line ",0
  204.  
  205. FIELD_OFFSET   DW      BLOCK_MSG, WORD_MSG, NONE_MSG, LINE_MSG
  206.  
  207. MENU           LABEL   BYTE
  208. DB " F2 Save  F3 New file  F4 Sort  F5 Lines/rec:",0
  209. DB "  F6 Key priority:",0, "  F7 ",0
  210. DB " F8 Type:",0, "   F9 Field:",0
  211. BLOCK_START  DB "   F10 Mark block start     ",0
  212. WORD_POS_MSG DB "   F10 Word position:",0, "     ",0
  213. LINE_POS_MSG DB "   F10 Mark line            ",0
  214. SPACES       DB "                            ",0
  215. END_MSG      DB                   "end  ",0
  216.  
  217.  
  218. M_DISPATCH     DB      UP_SCAN,    DOWN_SCAN,   PGUP_SCAN,      PGDN_SCAN
  219.                DB      LEFT_SCAN,  RIGHT_SCAN,  HOME_SCAN,      END_SCAN
  220.                DB      HOME_SCAN,  END_SCAN,    CTRL_HOME_SCAN, CTRL_END_SCAN
  221.                DB      F2_SCAN,    F3_SCAN,     F4_SCAN,        F5_SCAN
  222.                DB      F6_SCAN,    F7_SCAN,     F8_SCAN,        F9_SCAN
  223.                DB      F10_SCAN,   SHIFT_F5,    SHIFT_F6,       SHIFT_F9
  224.                DB      SHIFT_F10,  F1_SCAN,     ALT_F1
  225. M_LEN          EQU     $ - M_DISPATCH
  226.  
  227.                DW      UP,         DOWN,        PGUP,           PGDN
  228.                DW      LEFT,       RIGHT,       HOME_KEY,       END_KEY
  229.                DW      HOME_KEY,   END_KEY,     CTRL_HOME,      CTRL_END
  230.                DW      SAVE,       NEW_FILE,    SORT,           LINES_REC
  231.                DW      PRIORITY,   DIRECTION,   SORT_TYPE,      FIELD_TYPE
  232.                DW      BLOCKSTART, SH_LINE_REC, SH_PRIORITY,    SH_FIELD_TYPE
  233.                DW      SH_BLOCKSTART, HELP,     RESET
  234.  
  235. NOT_ENOUGH     DB      " Not enough memory.",0,"$"
  236. FILE_NOT_FOUND DB      " File not found.",0
  237. ESC_MSG        DB      "  Esc to Exit",0
  238. FILE_TOO_SMALL DB      " File too small.",0
  239. READ_FAIL      DB      " Read fail.",0
  240. LINE_TOO_LONG  DB      " Line too long.",0
  241. TOO_MANY_LINES DB      " Too many lines.",0
  242. ENTER_FILENAME DB      " Enter filename: ",0
  243. NAME_CURSOR    EQU     $ - ENTER_FILENAME
  244. FILENAME_LEN   EQU     80 - NAME_CURSOR - 1
  245.  
  246. SAVING         DB      " Saving...                  ",0
  247. SAVE_FAILED    DB      " Save failed; Esc to cancel.",0
  248. LOADING_FILE   DB      " Loading file...               ",0
  249. SAVE_FILE      DB      " Save modified file?  Y/N",0
  250. SORTING        DB      " Sorting...",0
  251.                DB      " Press Esc to abort",0
  252.  
  253. ;              CODE AREA
  254. ;              ---------
  255. MAIN           PROC    NEAR
  256.                CLD                             ;String instructions forward.
  257.  
  258.                MOV     AH,8
  259.                INT     10H
  260.                MOV     SCREEN_COLOR,AH
  261.  
  262.                MOV     BX,-1
  263.                MOV     AH,4AH                  ;Allocate memory.
  264.                INT     21H
  265.  
  266.                MOV     AX,OFFSET STACK_POINTER
  267.                ADD     AX,15
  268.                MOV     CL,4
  269.                SHR     AX,CL
  270.                MOV     CX,DS
  271.                ADD     AX,CX
  272.                MOV     INDEX_SEG,AX
  273.  
  274.                ADD     AX,INDEX_SIZE
  275.                MOV     TEXT_SEG,AX
  276.  
  277.                ADD     CX,BX                   ;Top of memory seg.
  278.                ADD     AX,READ_SIZE SHR 4
  279.                CMP     CX,AX
  280.                JAE     MEMORY_OK
  281.  
  282.                MOV     DX,OFFSET NOT_ENOUGH
  283.                JMP     ERROR_EXIT              ;If not enough, exit.
  284.  
  285. MEMORY_OK:     MOV     AH,4AH
  286.                INT     21H
  287.                MOV     AX,OFFSET STACK_POINTER
  288.                MOV     SP,AX                   ;Set up stack.
  289.  
  290.                SUB     CX,TEXT_SEG
  291.                MOV     AX,CX
  292.                XOR     DX,DX
  293.                MOV     BX,READ_SIZE SHR 4
  294.                DIV     BX
  295.                MOV     CL,4
  296.                SHL     DX,CL
  297.                MOV     MEM_TOP_OFF,DX          ;Memory top in reference
  298.                MUL     BX                      ; to TEXT_SEG in 32K
  299.                ADD     AX,TEXT_SEG             ; multiples.
  300.                MOV     MEM_TOP_SEG,AX
  301.  
  302.                XOR     BX,BX
  303.                MOV     AX,4406H                ;Input status.
  304.                INT     21H
  305.                OR      AL,AL
  306.                JNZ     PARSE
  307.                MOV     STDIN_FLAG,0
  308.  
  309.                CALL    VIDEO_SETUP
  310.                JMP     SHORT PARSE
  311.  
  312. ;---------------
  313.  
  314. NEXT_FILE:     CALL    GET_NAME
  315.                JC      EXIT
  316.  
  317. PARSE:         CALL    PARSE_IT
  318.                JC      ERROR
  319.                CMP     STDIN_FLAG,1
  320.                JZ      DO_STDIN
  321.                CALL    LOAD_FILE
  322.                JC      NEXT_FILE
  323.                JMP     SHORT NEXT_KEY
  324.  
  325. ;------------------
  326.  
  327. DO_STDIN:      XOR     BX,BX
  328.                CALL    READ_FILE2
  329.                JC      ERROR
  330.                CALL    INDEX
  331.                JC      ERROR
  332.                CALL    SORT2
  333.                MOV     BX,1
  334.                CALL    SAVE2
  335.                JC      ERROR
  336.                JMP     SHORT GOOD_EXIT
  337.  
  338. ;************* Main Loop *************;
  339.  
  340. NEXT_KEY:      CALL    UPDATE_MARK
  341.                CALL    UPDATE_TEXT
  342.                CALL    DISPLAY_MENU
  343.                CALL    CLEAR_KEY
  344.                MOV     DI,OFFSET M_DISPATCH
  345.                MOV     CX,M_LEN
  346.                CALL    DISPATCH
  347.                JC      EXIT
  348.                OR      AL,AL
  349.                JZ      NEXT_KEY
  350.                CALL    MINI_EDIT
  351.                JMP     NEXT_KEY
  352.  
  353. ;----------------------------------------------;
  354. ERROR_EXIT:    CALL    PRINT_STRING
  355.                MOV     AL,1
  356.                JMP     SHORT TERMINATE2
  357.  
  358. ERROR:         CALL    BEEP
  359.                MOV     AL,1                    ;Exit with ERRORLEVEL one.
  360.                CMP     STDIN_FLAG,1
  361.                JZ      DONE
  362.                CALL    CLOSE_SCREEN
  363.                JMP     SHORT TERMINATE
  364.  
  365. EXIT:          CALL    CLOSE_SCREEN
  366.  
  367. GOOD_EXIT:     XOR     AL,AL                   ;ERRORLEVEL zero.
  368.  
  369. TERMINATE:     CMP     STDIN_FLAG,1
  370.                JZ      DONE
  371. TERMINATE2:    PUSH    AX
  372.                MOV     DX,OFFSET SIGNATURE
  373.                CALL    PRINT_STRING
  374.                POP     AX
  375. DONE:          MOV     AH,4CH                  ;Terminate.
  376.                INT     21H
  377.  
  378. MAIN           ENDP
  379.  
  380. ;              ***************
  381. ;              * SUBROUTINES *
  382. ;              ***************
  383.  
  384. ;----------------------------------------------;
  385. MINI_EDIT:     CMP     AH,CR
  386.                JNZ     DO_MINI
  387.                CALL    GET_PARAMS
  388.                CALL    DOWN
  389.                MOV     CURSOR_COLUMN,0
  390.                MOV     START_COLUMN,0
  391.                JMP     SHORT EDIT_END
  392.  
  393. DO_MINI:       CMP     AH,SPACE
  394.                JB      EDIT_END
  395.                PUSH    DS
  396.                PUSH    ES
  397.  
  398.                MOV     DL,AH
  399.                MOV     AL,SIZE INDEX_REC
  400.                MUL     CURSOR_ROW
  401.                ADD     AX,TOP_LINE
  402.                MOV     BX,AX
  403.                MOV     CL,CURSOR_COLUMN
  404.                XOR     CH,CH
  405.                ADD     CX,START_COLUMN
  406.                MOV     DS,INDEX_SEG
  407.                MOV     ES,SEG_PTR[BX]
  408.                CMP     CX,TEXT_LEN[BX]
  409.                JAE     EDIT_DONE
  410.                MOV     DI,OFF_PTR[BX]
  411.                ADD     DI,CX
  412.                MOV     AL,DL
  413.                STOSB
  414.                POP     ES
  415.                POP     DS
  416.                MOV     MODIFY_FLAG,1
  417.                CALL    RIGHT
  418.                JMP     SHORT EDIT_END
  419.  
  420. EDIT_DONE:     POP     ES
  421.                POP     DS
  422. EDIT_END:      RET
  423.  
  424. ;----------------------------------------------;
  425. UPDATE_MARK:   CALL    GET_PRIORITY
  426.                MOV     AL,KEYS.KEY_FIELD[BP]
  427.                CMP     AL,BLOCK_TYPE
  428.                JNZ     CK_LINE_TYPE
  429.  
  430.                MOV     AX,KEYS.BLOCK_INDEX[BP]
  431.                CALL    CALC_DISP_REC
  432.                MOV     MARK_INDEX,AX
  433.                MOV     AX,KEYS.BLOCK_BEG[BP]
  434.                MOV     MARK_LEFT,AX
  435.                DEC     AX
  436.                ADD     AX,KEYS.BLOCK_LEN[BP]
  437.                MOV     MARK_RIGHT,AX
  438.                JMP     SHORT UPDATE_END
  439.  
  440. CK_LINE_TYPE:  CMP     AL,LINE_TYPE
  441.                JNZ     CK_WORD_TYPE
  442.                MOV     AX,KEYS.LINE_INDEX[BP]
  443.                CALL    CALC_DISP_REC
  444.                MOV     MARK_INDEX,AX
  445.                MOV     MARK_LEFT,0
  446.                MOV     AX,LONGEST_LINE
  447.                DEC     AX
  448.                MOV     MARK_RIGHT,AX
  449.                JMP     SHORT UPDATE_END
  450.  
  451. CK_WORD_TYPE:  CMP     AL,WORD_TYPE
  452.                JNZ     NO_TYPE
  453.                XOR     AX,AX
  454.                CALL    CALC_DISP_REC
  455.                PUSH    ES
  456.                PUSH    DS
  457.                MOV     ES,INDEX_SEG
  458.                MOV     BX,AX
  459.                CALL    WORD_ADDRESS
  460.                POP     DS
  461.                JNC     CK_MARK_WORD
  462. NO_WORD2:      POP     ES
  463.                JMP     SHORT NO_TYPE
  464.  
  465. CK_MARK_WORD:  CMP     BX,LAST_LINE
  466.                JA      NO_WORD2
  467. MARK_WORD:     MOV     AX,ES:OFF_PTR[BX]
  468.                POP     ES
  469.                MOV     MARK_INDEX,BX
  470.                SUB     DI,AX
  471.                MOV     MARK_LEFT,DI
  472.                SUB     SI,AX
  473.                MOV     MARK_RIGHT,SI
  474.                JMP     SHORT UPDATE_END
  475.  
  476. NO_TYPE:       MOV     MARK_INDEX,INACTIVE
  477.  
  478. UPDATE_END:    RET
  479.  
  480. ;-----------------
  481. ; INPUT:  AX = index
  482. ; OUTPUT: AX = first index offset of first whole record on screen.
  483.  
  484. CALC_DISP_REC: CALL    CALC_ROW
  485.                PUSH    AX
  486.                MOV     AX,TOP_LINE
  487.                XOR     DX,DX
  488.                DIV     CX
  489.                DIV     BX
  490.                MUL     BX
  491.                MUL     CX
  492.                POP     DX
  493.                ADD     AX,DX
  494.  
  495.                CMP     AX,TOP_LINE
  496.                JAE     CALC_END
  497.                MOV     DX,AX
  498.                MOV     AX,BX
  499.                MUL     CL
  500.                ADD     AX,DX
  501. CALC_END:      RET
  502.  
  503. ;---------------
  504. ;INPUT: AX=index; OUTPUT: AX=row in record.
  505.  
  506. CALC_ROW:      XOR     DX,DX
  507.                MOV     CX,SIZE INDEX_REC
  508.                DIV     CX
  509.                MOV     BL,LINES_PER_REC
  510.                XOR     BH,BH
  511.                INC     BX
  512.                DIV     BX
  513.                MOV     AX,DX
  514.                MUL     CX
  515.                RET
  516.  
  517. ;----------------------------------------------;
  518. ; INPUT:  BP=KEYS index; ES=INDEX_SEG or    TEMP_RECORD'S CS;
  519. ;                        BX=INDEX offset or TEMP_RECORD'S offset.
  520. ; OUTPUT: CF=1 if no word matching WORD_CNT found.
  521. ; ELSE:   CF=0; BX=word INDEX offset; DI -> word start offset;
  522. ;         SI -> word end.
  523.  
  524. WORD_ADDRESS:  MOV     DH,CS:LINES_PER_REC
  525.                INC     DH
  526.                MOV     DL,CS:KEYS.WORD_POS[BP]
  527.                OR      DL,DL
  528.                JS      REVERSE
  529.  
  530. NEXT_LINE:     MOV     DS,ES:SEG_PTR[BX]
  531.                MOV     SI,ES:OFF_PTR[BX]
  532.                MOV     CX,ES:TEXT_LEN[BX]
  533.                JCXZ    LOOP_LINE
  534.  
  535. FIND_WORD:     LODSB
  536.                CMP     AL,SPACE
  537.                JNZ     FIND_WORD_END
  538.                LOOP    FIND_WORD
  539.                JMP     SHORT LOOP_LINE
  540.  
  541. FIND_WORD_END: DEC     SI
  542.                MOV     DI,SI
  543. NEXT_END:      LODSB
  544.                CMP     AL,SPACE
  545.                JZ      FOUND_END2
  546.                LOOP    NEXT_END
  547.                INC     SI                      ;End of line.
  548.                INC     CX                      ;CX off by one
  549.  
  550. FOUND_END2:    DEC     DL
  551.                JZ      FOUND_WORD
  552.                DEC     CX
  553.                JNZ     FIND_WORD
  554.                JMP     SHORT LOOP_LINE
  555.  
  556. FOUND_WORD:    DEC     SI
  557.                DEC     SI
  558.                CLC
  559.                JMP     SHORT ADDRESS_END
  560.  
  561. LOOP_LINE:     ADD     BX,SIZE INDEX_REC
  562.                DEC     DH
  563.                JNZ     NEXT_LINE
  564.  
  565. NO_WORD:       STC
  566.  
  567. ADDRESS_END:   CLD
  568.                RET
  569.  
  570. ;---------------
  571.  
  572. REVERSE:       STD
  573.  
  574.                NEG     DL
  575.                MOV     AH,DH
  576.                DEC     AH
  577.                MOV     AL,SIZE INDEX_REC
  578.                MUL     AH
  579.                ADD     BX,AX
  580.  
  581. NEXT_LINE2:    MOV     DS,ES:SEG_PTR[BX]
  582.                MOV     SI,ES:OFF_PTR[BX]
  583.                MOV     CX,ES:TEXT_LEN[BX]
  584.                JCXZ    LOOP_LINE2
  585.                ADD     SI,CX
  586.                DEC     SI
  587.  
  588. FIND_WORD2:    LODSB
  589.                CMP     AL,SPACE
  590.                JNZ     WORD_END
  591.                LOOP    FIND_WORD2
  592.                JMP     SHORT LOOP_LINE2
  593.  
  594. WORD_END:      INC     SI
  595.                MOV     DI,SI
  596. NEXT_END2:     LODSB
  597.                CMP     AL,SPACE
  598.                JZ      FOUND_END3
  599.                LOOP    NEXT_END2
  600.                DEC     SI                      ;Start of line.
  601.                INC     CX                      ;CX off by one
  602.  
  603. FOUND_END3:    DEC     DL
  604.                JZ      FOUND_WORD2
  605.                DEC     CX
  606.                JNZ     FIND_WORD2
  607.                JMP     SHORT LOOP_LINE2
  608.  
  609. FOUND_WORD2:   INC     SI
  610.                INC     SI
  611.                XCHG    SI,DI
  612.                CLC
  613.                JMP     ADDRESS_END
  614.  
  615. LOOP_LINE2:    SUB     BX,SIZE INDEX_REC
  616.                DEC     DH
  617.                JNZ     NEXT_LINE2
  618.                JMP     NO_WORD
  619.  
  620. ;----------------------------------------------;
  621. UPDATE_TEXT:   MOV     DH,CURSOR_ROW
  622.                INC     DH
  623.                MOV     DL,CURSOR_COLUMN
  624.                CALL    SET_CURSOR
  625.                CALL    DISP_DISPLAY
  626.                RET
  627.  
  628. ;----------------------------------------------;
  629. ; OUTPUT: CF=1 if failed.
  630. LOAD_FILE:     CALL    ASCIIZ
  631.                CALL    READ_FILE
  632.                JC      DISP_ERROR
  633.                CALL    INDEX
  634.                JC      DISP_ERROR
  635.                CMP     LAST_LINE,0
  636.                MOV     SI,OFFSET FILE_TOO_SMALL
  637.                JBE     DISP_ERROR
  638.  
  639.                MOV     TOP_LINE,0
  640.                MOV     START_COLUMN,0
  641.  
  642.                MOV     MARK_INDEX,-1
  643.  
  644.                MOV     CURSOR_ROW,0
  645.                MOV     CURSOR_COLUMN,0
  646.                CLC
  647.                JMP     SHORT LOAD_END
  648.  
  649. DISP_ERROR:    CALL    CLEAR_MENU
  650.                CALL    WRITE_STRING
  651.                MOV     SI,OFFSET ESC_MSG
  652.                CALL    WRITE_STRING
  653.                CALL    BEEP
  654.                STC
  655.  
  656. LOAD_END:      RET
  657.  
  658. ;----------------------------------------------;
  659. ; OUTPUT: CF=1 if invalid switch.
  660.  
  661. PARSE_IT:      MOV     SI,81H
  662.                MOV     FILENAME,SI
  663.                CALL    CAPITALIZE
  664.                XOR     BP,BP
  665. NEXT_PARSE:    CALL    PARSE_DELIMIT
  666.                LODSB
  667.                CMP     AL,CR
  668.                CLC
  669.                JZ      PARSE_END
  670.  
  671. CK_SLASH:      CMP     AL,"/"
  672.                JNZ     DO_FILENAME
  673.                CALL    PARSE_DELIMIT
  674.                LODSB
  675.                CMP     AL,CR
  676.                CLC
  677.                JZ      PARSE_END
  678.  
  679.                CMP     AL,"1"
  680.                JB      CK_SWITCH
  681.                CMP     AL,"9"
  682.                JA      CK_SWITCH
  683.                DEC     SI
  684.                CALL    SW_BLOCK
  685.                JMP     NEXT_PARSE
  686.  
  687. CK_SWITCH:     MOV     CX,SWITCH_LEN
  688.                MOV     BX,CX
  689.                MOV     DI,OFFSET SWITCH_CHARS
  690.                MOV     DX,DI
  691.                ADD     DX,CX
  692.                REPNZ   SCASB
  693.                STC
  694.                JNZ     PARSE_END
  695.                SUB     BX,CX
  696.                DEC     BX
  697.                SHL     BX,1
  698.                ADD     BX,DX
  699.                CALL    [BX]                    ;Process the command.
  700.                JMP     NEXT_PARSE
  701.  
  702. DO_FILENAME:   DEC     SI
  703.                MOV     FILENAME,SI
  704. FIND_END:      LODSB
  705.                CMP     AL,"/"
  706.                JZ      FOUND_END
  707.                CMP     AL,SPACE
  708.                JA      FIND_END
  709. FOUND_END:     DEC     SI
  710.                JMP     NEXT_PARSE
  711.  
  712. PARSE_END:     RET
  713.  
  714. ;-----------------------------------------------------------------;
  715. ; INPUT: SI -> string;  OUTPUT SI -> first non-white space or CR. ;
  716. ;-----------------------------------------------------------------;
  717. PARSE_DELIMIT: PUSH    AX
  718. NEXT_DELIMIT:  LODSB                           ;Get a byte.
  719.                CMP     AL,CR
  720.                JZ      LEADING_END
  721.                CMP     AL,SPACE                ;Is it a space char or below?
  722.                JBE     NEXT_DELIMIT
  723.                CMP     AL,COMMA                ;Or comma?
  724.                JZ      NEXT_DELIMIT
  725.                CMP     AL,";"                  ;Or semicolon?
  726.                JZ      NEXT_DELIMIT            ;If yes, parse.
  727. LEADING_END:   DEC     SI                      ;Else, adjust pointer to
  728.                POP     AX
  729.                RET                             ; string start.
  730.  
  731. ;----------------------------------------------;
  732. ; INPUT:  SI -> string;  SI preserved.         ;
  733. ;----------------------------------------------;
  734. CAPITALIZE:    PUSH    SI
  735. NEXT_CAP:      LODSB
  736.                CMP     AL,CR
  737.                JZ      CAP_END
  738.                CMP     AL,"a"
  739.                JB      NEXT_CAP
  740.                CMP     AL,"z"
  741.                JA      NEXT_CAP
  742.                AND     BYTE PTR [SI - 1],5FH
  743.                JMP     NEXT_CAP
  744. CAP_END:       POP     SI
  745.                RET
  746.  
  747. ;----------------------------------------------;
  748. SW_PRIORITY:   CALL    DECIMAL_INPUT
  749.                DEC     AX
  750.                JS      SW_PEND
  751.                CMP     AX,KEY_MAX - 1
  752.                JA      SW_PEND
  753.                MOV     AH,SIZE SORT_KEY
  754.                MUL     AH
  755.                MOV     BP,AX
  756. SW_PEND:       RET
  757.  
  758. ;----------------------------------------------;
  759. SW_DIRECTION:  MOV     KEYS.SORT_DIRECTION[BP],DESCEND
  760.                RET
  761.  
  762. ;----------------------------------------------;
  763. SW_LINE:       MOV     KEYS.KEY_FIELD[BP],LINE_TYPE
  764.                CALL    DECIMAL_INPUT
  765.                DEC     AX
  766.                JS      SW_LINE_END
  767.                CMP     AX,LINES_REC_MAX - 1
  768.                JA      SW_LINE_END
  769.                CMP     AL,LINES_PER_REC
  770.                JA      SW_LINE_END
  771.                MOV     AH,SIZE INDEX_REC
  772.                MUL     AH
  773.                MOV     KEYS.LINE_INDEX[BP],AX
  774. SW_LINE_END:   RET
  775.  
  776. ;----------------------------------------------;
  777. SW_BLOCK:      MOV     KEYS.KEY_FIELD[BP],BLOCK_TYPE
  778.                CALL    DECIMAL_INPUT
  779.                OR      AX,AX
  780.                JZ      STORE_BEG
  781.                DEC     AX
  782. STORE_BEG:     MOV     KEYS.BLOCK_BEG[BP],AX
  783.                CALL    DECIMAL_INPUT
  784.                OR      AX,AX
  785.                JZ      SW_BLOCK_END
  786.                MOV     KEYS.BLOCK_LEN[BP],AX
  787.                CALL    DECIMAL_INPUT
  788.                DEC     AX
  789.                JS      SW_BLOCK_END
  790.                MOV     AH,SIZE INDEX_REC
  791.                MUL     AH
  792.                MOV     KEYS.BLOCK_INDEX[BP],AX
  793. SW_BLOCK_END:  RET
  794.  
  795. ;----------------------------------------------;
  796. SW_WORD:       MOV     KEYS.KEY_FIELD[BP],WORD_TYPE
  797.                CALL    PARSE_DELIMIT
  798.                MOV     DI,"+"
  799.                CMP     BYTE PTR [SI],"+"
  800.                JZ      GET_SIGN
  801.                CMP     BYTE PTR [SI],"-"
  802.                JNZ     GET_WORD_CNT
  803.                MOV     DI,"-"
  804. GET_SIGN:      INC     SI
  805. GET_WORD_CNT:  CALL    DECIMAL_INPUT
  806.                CMP     AX,1
  807.                JB      SW_WORD_END
  808.                CMP     AX,9
  809.                JA      SW_WORD_END
  810.                CMP     DI,"+"
  811.                JZ      STORE_CNT
  812.                NEG     AL
  813. STORE_CNT:     MOV     KEYS.WORD_POS[BP],AL
  814. SW_WORD_END:   RET
  815.  
  816. ;----------------------------------------------;
  817. SW_RECORDS:    CALL    DECIMAL_INPUT
  818.                DEC     AX
  819.                JS      SW_REND
  820.                CMP     AX,LINES_REC_MAX - 1
  821.                JA      SW_REND
  822.                MOV     LINES_PER_REC,AL
  823. SW_REND:       RET
  824.  
  825. ;----------------------------------------------;
  826. SW_NUMERIC:    MOV     KEYS.KEY_TYPE[BP],NUMERIC_TYPE
  827.                RET
  828.  
  829. ;----------------------------------------------;
  830. SW_CASE:       MOV     CASE,0FFH
  831.                RET
  832.  
  833. ;----------------------------------------------;
  834. DECIMAL_INPUT: CALL    PARSE_DELIMIT
  835.                XOR     BX,BX                   ;Start with zero as number.
  836. NEXT_DECIMAL:  LODSB                           ;Get a character.
  837.                SUB     AL,"0"                  ;ASCII to binary.
  838.                JC      DECIMAL_END             ;If not between 0 and 9, skip.
  839.                CMP     AL,9
  840.                JA      DECIMAL_END
  841.                CBW                             ;Convert byte to word.
  842.                XCHG    AX,BX                   ;Swap old and new number.
  843.                MOV     CX,10                   ;Shift to left by multiplying
  844.                MUL     CX                      ; last entry by ten.
  845.                ADD     BX,AX                   ;Add new number and store in BX.
  846.                JMP     NEXT_DECIMAL
  847. DECIMAL_END:   DEC     SI                      ;SI -> string end.
  848.                MOV     AX,BX
  849.                RET
  850.  
  851. ;----------------------------------------------;
  852. ASCIIZ:        MOV     SI,FILENAME
  853. NEXT_ASCIIZ:   LODSB
  854.                CMP     AL,"/"
  855.                JZ      ASCIIZ_END
  856.                CMP     AL,SPACE
  857.                JA      NEXT_ASCIIZ
  858. ASCIIZ_END:    MOV     BYTE PTR [SI-1],0
  859.                RET
  860.  
  861. ;----------------------------------------------;
  862. ; OUTPUT: CF=1 if Esc pressed; FILENAME -> filename.
  863.  
  864. GET_NAME:      CALL    MENU_OFFSET
  865.                ADD     DI,CRT_WIDTH
  866.                MOV     BH,COLOR.B
  867.                MOV     SI,OFFSET ENTER_FILENAME
  868.                CALL    WRITE_STRING
  869.                MOV     SI,FILENAME
  870.                MOV     FILE_CURSOR,SI
  871.                MOV     DI,SI
  872.                MOV     CX,FILENAME_LEN
  873.                MOV     LINE_START,DI
  874.                ADD     DI,CX
  875.                MOV     LINE_END,DI
  876.  
  877. GET_END:       LODSB
  878.                CMP     AL,"/"
  879.                JZ      GOT_END3
  880.                CMP     AL,SPACE
  881.                JA      GET_END
  882.  
  883. GOT_END3:      DEC     SI
  884.                MOV     CX,LINE_END
  885.                SUB     CX,SI
  886.                MOV     AL,SPACE
  887.                MOV     DI,SI
  888.                REP     STOSB
  889.                XOR     AL,AL
  890.                STOSB
  891.                MOV     AL,CR
  892.                STOSB
  893.  
  894. NEXT_FILENAME: CALL    MENU_OFFSET
  895.                ADD     DI,CRT_WIDTH
  896.                ADD     DI,NAME_CURSOR * 2
  897.                MOV     BH,COLOR.B
  898.                MOV     SI,LINE_START
  899.                CALL    WRITE_STRING
  900.  
  901.                MOV     DI,FILE_CURSOR
  902.                MOV     DX,DI
  903.                ADD     DL,NAME_CURSOR
  904.                SUB     DX,LINE_START
  905.                MOV     DH,ROWS
  906.                CALL    SET_CURSOR
  907.                CALL    EDITOR
  908.                MOV     FILE_CURSOR,DI
  909.                JC      GET_NAME_END
  910.                CMP     AH,ENTER_SCAN
  911.                JNZ     NEXT_FILENAME
  912. GET_NAME_END:  RET
  913.  
  914. ;----------------------------------------------;
  915. CK_MODIFIED:   CMP     MODIFY_FLAG,1
  916.                MOV     MODIFY_FLAG,0
  917.                JNZ     MODIFIED_END
  918.                CALL    HIDE_CURSOR
  919.                CALL    CLEAR_MENU
  920.                MOV     BH,COLOR.B
  921.                MOV     SI,OFFSET SAVE_FILE
  922.                CALL    WRITE_STRING
  923.                CALL    CLEAR_KEY
  924. NEXT_MODIFIED: CALL    GETKEY
  925.                JC      MODIFIED_END
  926.                AND     AH,5FH
  927.                CMP     AH,"N"
  928.                JZ      MODIFIED_END
  929.                CMP     AH,"Y"
  930.                JNZ     NEXT_MODIFIED
  931.                CALL    SAVE
  932. MODIFIED_END:  RET
  933.  
  934. ;----------------------------------------------;
  935. SAVE:          CALL    CLEAR_MENU
  936. NEXT_SAVE:     CALL    GET_NAME
  937.                JC      SAVE_END
  938.  
  939.                CALL    ASCIIZ
  940.                MOV     DX,FILENAME
  941.                MOV     AX,3D01H
  942.                INT     21H
  943.                JC      DISP_SAVE_MSG
  944.                MOV     BX,AX
  945.                MOV     AX,4400H
  946.                INT     21H
  947.                MOV     AH,3EH
  948.                INT     21H
  949.                TEST    DX,10000000B
  950.                STC
  951.                JNZ     SAVE_FAIL2
  952.  
  953. DISP_SAVE_MSG: CALL    MENU_OFFSET
  954.                MOV     BH,COLOR.B
  955.                MOV     SI,OFFSET SAVING
  956.                CALL    WRITE_STRING
  957.                CALL    DOS_CURSOR
  958.                MOV     DX,FILENAME
  959.                XOR     CX,CX
  960.                MOV     AH,3CH
  961.                INT     21H
  962.                JC      SAVE_FAIL2
  963.                MOV     BX,AX
  964.  
  965. SAVE2:         PUSH    DS
  966.                PUSH    ES
  967.                MOV     BP,LAST_LINE
  968.                MOV     ES,INDEX_SEG
  969.                XOR     DI,DI
  970. NEXT_SAVE2:    MOV     DX,ES:OFF_PTR[DI]
  971.                MOV     DS,ES:SEG_PTR[DI]
  972.                MOV     CX,ES:LINE_LEN[DI]
  973.                MOV     AH,40H
  974.                INT     21H
  975.                JC      SAVE_FAIL
  976.                ADD     DI,SIZE INDEX_REC
  977.                CMP     DI,BP
  978.                JBE     NEXT_SAVE2
  979.  
  980.                MOV     AH,3EH
  981.                INT     21H
  982.  
  983.                POP     ES
  984.                POP     DS
  985.                PUSHF
  986.                CALL    CLEAR_KEY
  987.                POPF
  988. SAVE_END:      RET
  989.  
  990.  
  991. SAVE_FAIL:     POP     ES
  992.                POP     DS
  993.                MOV     AH,3EH
  994.                INT     21H
  995. SAVE_FAIL2:    CMP     STDIN_FLAG,1
  996.                JZ      SAVE_END
  997.                CALL    CLEAR_KEY
  998.                CALL    MENU_OFFSET
  999.                MOV     BH,COLOR.B
  1000.                MOV     SI,OFFSET SAVE_FAILED
  1001.                CALL    WRITE_STRING
  1002.                CALL    BEEP
  1003.                JMP     NEXT_SAVE
  1004.  
  1005. ;----------------------------------------------;
  1006. NEW_FILE:      CALL    CK_MODIFIED
  1007.                CALL    CLEAR_MENU
  1008. NEXT_NEW:      CALL    GET_NAME
  1009.                JC      NEW_END
  1010.                CALL    PARSE_IT
  1011.                CALL    LOAD_FILE
  1012.                JC      NEXT_NEW
  1013. NEW_END:       RET
  1014.  
  1015. ;----------------------------------------------;
  1016. SORT_INDEX     DW      ?                       ;Index row for sort key.
  1017. TEMP_RECORD    DB      LINES_REC_MAX * SIZE INDEX_REC DUP (?)
  1018. TEMP_FLAG      DB      ?                       ;=1 if temporary swap in progress
  1019. SOURCE         DW      ?
  1020. DESTINATION    DW      ?
  1021.  
  1022. SOURCE_INTEGER       DB      LINE_MAX + 2 DUP (?)
  1023. DESTINATION_INTEGER  DB      LINE_MAX + 2 DUP (?)
  1024. SOURCE_DECIMAL       DB      LINE_MAX + 2 DUP (?)
  1025. DESTINATION_DECIMAL  DB      LINE_MAX + 2 DUP (?)
  1026.  
  1027. SORT:          CALL    HIDE_CURSOR
  1028.                CALL    CLEAR_MENU
  1029.                PUSH    DI
  1030.                MOV     SI,OFFSET SORTING
  1031.                CALL    WRITE_STRING
  1032.                POP     DI
  1033.                ADD     DI,CRT_WIDTH
  1034.                CALL    WRITE_STRING
  1035. SORT2:         PUSH    WORD PTR CURRENT_KEY
  1036.                MOV     CURRENT_KEY,KEY_MAX - 1
  1037.  
  1038. NEXT_SORT:     CALL    GET_PRIORITY
  1039.                MOV     AL,JB_CODE
  1040.                CMP     KEYS.SORT_DIRECTION[BP],ASCEND
  1041.                JZ      GET_KEY_TYPE
  1042.                MOV     AL,JA_CODE
  1043.  
  1044. GET_KEY_TYPE:  MOV     BL,KEYS.KEY_TYPE[BP]
  1045.                MOV     AH,KEYS.KEY_FIELD[BP]
  1046.  
  1047.                CMP     AH,LINE_TYPE
  1048.                JNZ     CK_BLOCK_SORT
  1049.                CMP     BL,ALPHA_TYPE
  1050.                JZ      DO_ALPHA_LINE
  1051.                CALL    SORT_LINE_N
  1052.                JMP     SHORT LOOP_SORT
  1053. DO_ALPHA_LINE: CALL    SORT_LINE_A
  1054.                JMP     SHORT LOOP_SORT
  1055.  
  1056. CK_BLOCK_SORT: CMP     AH,BLOCK_TYPE
  1057.                JNZ     CK_WORD_SORT
  1058.                CMP     BL,ALPHA_TYPE
  1059.                JZ      DO_ALPHA_BLK
  1060.                CALL    SORT_BLOCK_N
  1061.                JMP     SHORT LOOP_SORT
  1062. DO_ALPHA_BLK:  CALL    SORT_BLOCK_A
  1063.                JMP     SHORT LOOP_SORT
  1064.  
  1065. CK_WORD_SORT:  CMP     AH,WORD_TYPE
  1066.                JNZ     LOOP_SORT
  1067.                CMP     BL,ALPHA_TYPE
  1068.                JZ      DO_ALPHA_WORD
  1069.                CALL    SORT_WORD_N
  1070.                JMP     SHORT LOOP_SORT
  1071. DO_ALPHA_WORD: CALL    SORT_WORD_A
  1072.  
  1073. LOOP_SORT:     DEC     CURRENT_KEY
  1074.                JNS     NEXT_SORT
  1075.  
  1076. SORT_END:      POP     WORD PTR CURRENT_KEY
  1077.                CALL    CLEAR_KEY
  1078.                RET
  1079.  
  1080. ;----------------------------------------------;
  1081. SORT_LINE_A:   PUSH    DS
  1082.                PUSH    ES
  1083.  
  1084.                MOV     BYTE PTR LINE_JMP,AL
  1085.                MOV     MODIFY_FLAG,1
  1086.  
  1087.                MOV     AX,KEYS.LINE_INDEX[BP]
  1088.                CALL    CALC_ROW
  1089.                MOV     SORT_INDEX,AX
  1090.                XOR     SI,SI                   ;Source INDEX pointer.
  1091.                MOV     DI,INDEX_PER_REC        ;Destination INDEX pointer.
  1092.  
  1093. NEXT_SLINE:    MOV     AX,40H
  1094.                MOV     ES,AX
  1095.                MOV     AX,ES:[1AH]
  1096.                CMP     AX,ES:[1CH]
  1097.                JZ      CK_LINE_DONE
  1098.                CALL    GETKEY
  1099.                JNC     CK_LINE_DONE
  1100.                JMP     SORT_LINE_END
  1101.  
  1102. CK_LINE_DONE:  MOV     AX,DI
  1103.                ADD     AX,INDEX_PER_REC
  1104.                SUB     AX,SIZE INDEX_REC
  1105.                CMP     AX,LAST_LINE
  1106.                JBE     DO_LINE_SORT
  1107.                JMP     SORT_LINE_END
  1108.  
  1109. DO_LINE_SORT:  PUSH    SI
  1110.                PUSH    DI
  1111.                MOV     BX,SI
  1112.                MOV     DX,DI
  1113.                MOV     TEMP_FLAG,0
  1114.  
  1115. NEXT_LINE_REC: MOV     SI,BX
  1116.                MOV     DI,DX
  1117.                ADD     SI,CS:SORT_INDEX
  1118.                ADD     DI,CS:SORT_INDEX
  1119.                MOV     AX,CS:INDEX_SEG
  1120.                MOV     DS,AX
  1121.                CMP     CS:TEMP_FLAG,1
  1122.                JNZ     GET_LINE_LEN
  1123.                MOV     AX,CS
  1124.  
  1125. GET_LINE_LEN:  MOV     ES,AX
  1126.                MOV     AX,ES:TEXT_LEN[DI]
  1127.                MOV     CX,TEXT_LEN[SI]
  1128.                MOV     CH,AL
  1129.  
  1130.                MOV     AX,ES:OFF_PTR[DI]
  1131.                MOV     ES,ES:SEG_PTR[DI]
  1132.                MOV     DI,AX
  1133.                MOV     AX,OFF_PTR[SI]
  1134.                MOV     DS,SEG_PTR[SI]
  1135.                MOV     SI,AX
  1136.                JMP     SHORT LINE_LENGTH
  1137.  
  1138. NEXT_LCOMPARE: DEC     CL
  1139.                DEC     CH
  1140. LINE_LENGTH:   OR      CL,CL
  1141.                JZ      CK_LINE_LEN
  1142.                OR      CH,CH
  1143.                JNZ     LINE_BYTE
  1144. CK_LINE_LEN:   CMP     CL,CH
  1145.                JB      LINE_JMP
  1146.                JZ      NO_LINE_SWAP
  1147.                INC     CX
  1148.                CLC
  1149.                JMP     SHORT LINE_JMP
  1150.  
  1151. LINE_BYTE:     LODSB
  1152.                MOV     AH,ES:[DI]
  1153.                INC     DI
  1154.                CMP     AL,"a"
  1155.                JB      GET_LDEST
  1156.                CMP     AL,"z"
  1157.                JA      GET_LDEST
  1158.                AND     AL,CS:CASE
  1159. GET_LDEST:     CMP     AH,"a"
  1160.                JB      LCOMPARE
  1161.                CMP     AH,"z"
  1162.                JA      LCOMPARE
  1163.                AND     AH,CS:CASE
  1164.  
  1165. LCOMPARE:      CMP     AL,AH
  1166.  
  1167. LINE_JMP:      JB      NO_LINE_SWAP
  1168.                JZ      NEXT_LCOMPARE
  1169.  
  1170. LINE_SWAP:     CMP     CS:TEMP_FLAG,1
  1171.                JZ      CK_LINE_SWAP
  1172.                MOV     SI,DX
  1173.                MOV     DS,CS:INDEX_SEG
  1174.                MOV     DX,OFFSET TEMP_RECORD
  1175.                MOV     DI,DX
  1176.                MOV     AX,CS
  1177.                MOV     ES,AX
  1178.                MOV     CX,CS:INDEX_PER_REC
  1179.                REP     MOVSB
  1180.                MOV     CS:TEMP_FLAG,1
  1181.  
  1182. CK_LINE_SWAP:  MOV     AX,CS:INDEX_SEG
  1183.                MOV     DS,AX
  1184.                MOV     ES,AX
  1185.                MOV     SI,BX
  1186.                MOV     DI,SI
  1187.                MOV     CX,CS:INDEX_PER_REC
  1188.                ADD     DI,CX
  1189.                REP     MOVSB
  1190.  
  1191.                SUB     BX,CS:INDEX_PER_REC
  1192.                JS      NO_LINE_SWAP
  1193.                JMP     NEXT_LINE_REC
  1194.  
  1195. NO_LINE_SWAP:  MOV     AX,CS
  1196.                MOV     DS,AX
  1197.                CMP     TEMP_FLAG,1
  1198.                JNZ     NO_LINSERT
  1199.                MOV     SI,OFFSET TEMP_RECORD
  1200.                MOV     ES,INDEX_SEG
  1201.                MOV     DI,BX
  1202.                MOV     CX,INDEX_PER_REC
  1203.                ADD     DI,CX
  1204.                REP     MOVSB
  1205.  
  1206. NO_LINSERT:    POP     DI
  1207.                POP     SI
  1208.                MOV     AX,INDEX_PER_REC
  1209.                ADD     SI,AX
  1210.                ADD     DI,AX
  1211.                JMP     NEXT_SLINE
  1212.  
  1213. SORT_LINE_END: POP     ES
  1214.                POP     DS
  1215.                RET
  1216.  
  1217. ;----------------------------------------------;
  1218. SORT_BLOCK_A:  PUSH    DS
  1219.                PUSH    ES
  1220.  
  1221.                MOV     BYTE PTR BLOCK_JMP,AL
  1222.                CMP     KEYS.BLOCK_BEG,INACTIVE
  1223.                JNZ     DO_SORT_BLK
  1224.                JMP     SORT_BLK_END
  1225.  
  1226. DO_SORT_BLK:   MOV     MODIFY_FLAG,1
  1227.                MOV     AX,KEYS.BLOCK_INDEX[BP]
  1228.                CALL    CALC_ROW
  1229.                MOV     SORT_INDEX,AX
  1230.  
  1231.                XOR     SI,SI                   ;Source INDEX pointer.
  1232.                MOV     DI,INDEX_PER_REC        ;Destination INDEX pointer.
  1233.  
  1234. NEXT_BLK:      MOV     AX,40H
  1235.                MOV     ES,AX
  1236.                MOV     AX,ES:[1AH]
  1237.                CMP     AX,ES:[1CH]
  1238.                JZ      CK_BLK_DONE
  1239.                CALL    GETKEY
  1240.                JNC     CK_BLK_DONE
  1241.                JMP     SORT_BLK_END
  1242.  
  1243. CK_BLK_DONE:   MOV     AX,DI
  1244.                ADD     AX,INDEX_PER_REC
  1245.                SUB     AX,SIZE INDEX_REC
  1246.                CMP     AX,LAST_LINE
  1247.                JBE     DO_BLK_SORT
  1248.                JMP     SORT_BLK_END
  1249.  
  1250. DO_BLK_SORT:   PUSH    SI
  1251.                PUSH    DI
  1252.                MOV     BX,SI
  1253.                MOV     DX,DI
  1254.                MOV     TEMP_FLAG,0
  1255.  
  1256. NEXT_BLK_REC:  MOV     SI,BX
  1257.                MOV     DI,DX
  1258.                ADD     SI,CS:SORT_INDEX
  1259.                ADD     DI,CS:SORT_INDEX
  1260.                MOV     AX,CS:INDEX_SEG
  1261.                MOV     DS,AX
  1262.                CMP     CS:TEMP_FLAG,1
  1263.                JNZ     GET_BLK_LEN
  1264.                MOV     AX,CS
  1265.  
  1266. GET_BLK_LEN:   MOV     ES,AX
  1267.                MOV     AX,ES:TEXT_LEN[DI]
  1268.                MOV     CX,TEXT_LEN[SI]
  1269.                MOV     CH,AL
  1270.  
  1271.                MOV     AX,ES:OFF_PTR[DI]
  1272.                MOV     ES,ES:SEG_PTR[DI]
  1273.                MOV     DI,AX
  1274.                MOV     AX,OFF_PTR[SI]
  1275.                MOV     DS,SEG_PTR[SI]
  1276.                MOV     SI,AX
  1277.                MOV     AX,CS:KEYS.BLOCK_BEG[BP]
  1278.                ADD     SI,AX
  1279.                ADD     DI,AX
  1280.  
  1281.                SUB     CL,AL
  1282.                JNS     BLK_LEN2
  1283.                XOR     CL,CL
  1284. BLK_LEN2:      SUB     CH,AL
  1285.                JNS     BLK_LEN3
  1286.                XOR     CH,CH
  1287. BLK_LEN3:      MOV     AX,CS:KEYS.BLOCK_LEN[BP]
  1288.                CMP     CL,AL
  1289.                JB      BLK_LEN4
  1290.                MOV     CL,AL
  1291. BLK_LEN4:      CMP     CH,AL
  1292.                JB      BLK_LENGTH
  1293.                MOV     CH,AL
  1294.                JMP     SHORT BLK_LENGTH
  1295.  
  1296. NEXT_BCOMPARE: DEC     CL
  1297.                DEC     CH
  1298. BLK_LENGTH:    OR      CL,CL
  1299.                JZ      CK_BLK_LEN
  1300.                OR      CH,CH
  1301.                JNZ     BLK_BYTE
  1302. CK_BLK_LEN:    CMP     CL,CH
  1303.                JB      BLOCK_JMP
  1304.                JZ      NO_BLK_SWAP
  1305.                INC     CX
  1306.                CLC
  1307.                JMP     SHORT BLOCK_JMP
  1308.  
  1309. BLK_BYTE:      LODSB
  1310.                MOV     AH,ES:[DI]
  1311.                INC     DI
  1312.                CMP     AL,"a"
  1313.                JB      GET_BDEST
  1314.                CMP     AL,"z"
  1315.                JA      GET_BDEST
  1316.                AND     AL,CS:CASE
  1317. GET_BDEST:     CMP     AH,"a"
  1318.                JB      BCOMPARE
  1319.                CMP     AH,"z"
  1320.                JA      BCOMPARE
  1321.                AND     AH,CS:CASE
  1322.  
  1323. BCOMPARE:      CMP     AL,AH
  1324.  
  1325. BLOCK_JMP:     JB      NO_BLK_SWAP
  1326.                JZ      NEXT_BCOMPARE
  1327.  
  1328. BLK_SWAP:      CMP     CS:TEMP_FLAG,1
  1329.                JZ      CK_BLK_SWAP
  1330.                MOV     SI,DX
  1331.                MOV     DS,CS:INDEX_SEG
  1332.                MOV     DX,OFFSET TEMP_RECORD
  1333.                MOV     DI,DX
  1334.                MOV     AX,CS
  1335.                MOV     ES,AX
  1336.                MOV     CX,CS:INDEX_PER_REC
  1337.                REP     MOVSB
  1338.                MOV     CS:TEMP_FLAG,1
  1339.  
  1340. CK_BLK_SWAP:   MOV     AX,CS:INDEX_SEG
  1341.                MOV     DS,AX
  1342.                MOV     ES,AX
  1343.                MOV     SI,BX
  1344.                MOV     DI,SI
  1345.                MOV     CX,CS:INDEX_PER_REC
  1346.                ADD     DI,CX
  1347.                REP     MOVSB
  1348.  
  1349.                SUB     BX,CS:INDEX_PER_REC
  1350.                JS      NO_BLK_SWAP
  1351.                JMP     NEXT_BLK_REC
  1352.  
  1353. NO_BLK_SWAP:   MOV     AX,CS
  1354.                MOV     DS,AX
  1355.                CMP     TEMP_FLAG,1
  1356.                JNZ     NO_BINSERT
  1357.                MOV     SI,OFFSET TEMP_RECORD
  1358.                MOV     ES,INDEX_SEG
  1359.                MOV     DI,BX
  1360.                MOV     CX,INDEX_PER_REC
  1361.                ADD     DI,CX
  1362.                REP     MOVSB
  1363.  
  1364. NO_BINSERT:    POP     DI
  1365.                POP     SI
  1366.                MOV     AX,INDEX_PER_REC
  1367.                ADD     SI,AX
  1368.                ADD     DI,AX
  1369.                JMP     NEXT_BLK
  1370.  
  1371. SORT_BLK_END:  POP     ES
  1372.                POP     DS
  1373.                RET
  1374.  
  1375. ;----------------------------------------------;
  1376. SORT_WORD_A:   PUSH    DS
  1377.                PUSH    ES
  1378.  
  1379.                MOV     BYTE PTR WORD_JMP,AL
  1380.                MOV     MODIFY_FLAG,1
  1381.  
  1382.                XOR     SI,SI
  1383.                MOV     DI,INDEX_PER_REC
  1384.  
  1385. NEXT_WLINE:    MOV     AX,40H
  1386.                MOV     ES,AX
  1387.                MOV     AX,ES:[1AH]
  1388.                CMP     AX,ES:[1CH]
  1389.                JZ      CK_WORD_DONE
  1390.                CALL    GETKEY
  1391.                JNC     CK_WORD_DONE
  1392.                JMP     SORT_WORD_END
  1393.  
  1394. CK_WORD_DONE:  MOV     AX,DI
  1395.                ADD     AX,INDEX_PER_REC
  1396.                SUB     AX,SIZE INDEX_REC
  1397.                CMP     AX,LAST_LINE
  1398.                JBE     DO_WORD_SORT
  1399.                JMP     SORT_WORD_END
  1400.  
  1401. DO_WORD_SORT:  PUSH    SI
  1402.                PUSH    DI
  1403.                MOV     SOURCE,SI
  1404.                MOV     DESTINATION,DI
  1405.                MOV     TEMP_FLAG,0
  1406.  
  1407. NEXT_WORD_REC: MOV     ES,CS:INDEX_SEG
  1408.                MOV     BX,CS:SOURCE
  1409.                CALL    WORD_ADDRESS
  1410.                MOV     AX,DS
  1411.                PUSH    AX
  1412.                JC      STORE_SLEN
  1413.                MOV     CX,SI
  1414.                SUB     CX,DI
  1415.                INC     CX
  1416. STORE_SLEN:    PUSH    CX
  1417.                PUSH    DI
  1418.  
  1419.                CMP     CS:TEMP_FLAG,1
  1420.                JNZ     GET_DEST_WORD
  1421.                MOV     AX,CS
  1422.                MOV     ES,AX
  1423.  
  1424. GET_DEST_WORD: MOV     BX,CS:DESTINATION
  1425.                CALL    WORD_ADDRESS
  1426.                MOV     AX,DS
  1427.                MOV     ES,AX
  1428.                JC      GOT_DEST_WORD
  1429.                MOV     CX,SI
  1430.                SUB     CX,DI
  1431.                INC     CX
  1432. GOT_DEST_WORD: MOV     CH,CL
  1433.                POP     SI
  1434.                POP     AX
  1435.                MOV     CL,AL
  1436.                POP     DS
  1437.                JMP     SHORT WORD_LENGTH
  1438.  
  1439. NEXT_WCOMPARE: DEC     CL
  1440.                DEC     CH
  1441. WORD_LENGTH:   OR      CL,CL
  1442.                JZ      CK_WORD_LEN
  1443.                OR      CH,CH
  1444.                JNZ     WORD_BYTE
  1445. CK_WORD_LEN:   CMP     CL,CH
  1446.                JB      WORD_JMP
  1447.                JZ      NO_WORD_SWAP
  1448.                INC     CX
  1449.                CLC
  1450.                JMP     SHORT WORD_JMP
  1451.  
  1452. WORD_BYTE:     LODSB
  1453.                MOV     AH,ES:[DI]
  1454.                INC     DI
  1455.                CMP     AL,"a"
  1456.                JB      GET_WDEST
  1457.                CMP     AL,"z"
  1458.                JA      GET_WDEST
  1459.                AND     AL,CS:CASE
  1460. GET_WDEST:     CMP     AH,"a"
  1461.                JB      WCOMPARE
  1462.                CMP     AH,"z"
  1463.                JA      WCOMPARE
  1464.                AND     AH,CS:CASE
  1465.  
  1466. WCOMPARE:      CMP     AL,AH
  1467.  
  1468. WORD_JMP:      JB      NO_WORD_SWAP
  1469.                JZ      NEXT_WCOMPARE
  1470.  
  1471. WORD_SWAP:     CMP     CS:TEMP_FLAG,1
  1472.                JZ      CK_WORD_SWAP
  1473.                MOV     SI,CS:DESTINATION
  1474.                MOV     DS,CS:INDEX_SEG
  1475.                MOV     DI,OFFSET TEMP_RECORD
  1476.                MOV     CS:DESTINATION,DI
  1477.                MOV     AX,CS
  1478.                MOV     ES,AX
  1479.                MOV     CX,CS:INDEX_PER_REC
  1480.                REP     MOVSB
  1481.                MOV     CS:TEMP_FLAG,1
  1482.  
  1483. CK_WORD_SWAP:  MOV     AX,CS:INDEX_SEG
  1484.                MOV     DS,AX
  1485.                MOV     ES,AX
  1486.                MOV     SI,CS:SOURCE
  1487.                MOV     DI,SI
  1488.                MOV     CX,CS:INDEX_PER_REC
  1489.                MOV     AX,CX
  1490.                ADD     DI,CX
  1491.                REP     MOVSB
  1492.  
  1493.                SUB     CS:SOURCE,AX
  1494.                JS      NO_WORD_SWAP
  1495.                JMP     NEXT_WORD_REC
  1496.  
  1497. NO_WORD_SWAP:  MOV     AX,CS
  1498.                MOV     DS,AX
  1499.                CMP     TEMP_FLAG,1
  1500.                JNZ     NO_WINSERT
  1501.                MOV     SI,OFFSET TEMP_RECORD
  1502.                MOV     ES,INDEX_SEG
  1503.                MOV     DI,SOURCE
  1504.                MOV     CX,INDEX_PER_REC
  1505.                ADD     DI,CX
  1506.                REP     MOVSB
  1507.  
  1508. NO_WINSERT:    POP     DI
  1509.                POP     SI
  1510.                MOV     AX,INDEX_PER_REC
  1511.                ADD     SI,AX
  1512.                ADD     DI,AX
  1513.                JMP     NEXT_WLINE
  1514.  
  1515. SORT_WORD_END: POP     ES
  1516.                POP     DS
  1517.                RET
  1518.  
  1519. ;----------------------------------------------;
  1520. SORT_LINE_N:   PUSH    DS
  1521.                PUSH    ES
  1522.  
  1523.                MOV     BYTE PTR LINE_JMPN1,AL
  1524.                MOV     BYTE PTR LINE_JMPN2,AL
  1525.                MOV     BYTE PTR LINE_JMPN3,AL
  1526.                MOV     MODIFY_FLAG,1
  1527.  
  1528.                MOV     AX,KEYS.LINE_INDEX[BP]
  1529.                CALL    CALC_ROW
  1530.                MOV     SORT_INDEX,AX
  1531.                XOR     SI,SI                   ;Source INDEX pointer.
  1532.                MOV     DI,INDEX_PER_REC        ;Destination INDEX pointer.
  1533.  
  1534. NEXT_SLINEN:   MOV     AX,40H
  1535.                MOV     ES,AX
  1536.                MOV     AX,ES:[1AH]
  1537.                CMP     AX,ES:[1CH]
  1538.                JZ      CK_LINE_DONEN
  1539.                CALL    GETKEY
  1540.                JNC     CK_LINE_DONEN
  1541.                JMP     SORT_LINE_ENDN
  1542.  
  1543. CK_LINE_DONEN: MOV     AX,DI
  1544.                ADD     AX,INDEX_PER_REC
  1545.                SUB     AX,SIZE INDEX_REC
  1546.                CMP     AX,LAST_LINE
  1547.                JBE     DO_LINE_SORTN
  1548.                JMP     SORT_LINE_ENDN
  1549.  
  1550. DO_LINE_SORTN: PUSH    SI
  1551.                PUSH    DI
  1552.                MOV     SOURCE,SI
  1553.                MOV     DESTINATION,DI
  1554.                MOV     TEMP_FLAG,0
  1555.  
  1556. NEXT_LINE_RECN:MOV     DI,CS:SOURCE
  1557.                ADD     DI,CS:SORT_INDEX
  1558.                MOV     DS,CS:INDEX_SEG
  1559.                MOV     CX,TEXT_LEN[DI]
  1560.                MOV     SI,OFF_PTR[DI]
  1561.                MOV     DS,SEG_PTR[DI]
  1562.  
  1563.                MOV     AX,CS
  1564.                MOV     ES,AX
  1565.                MOV     DI,OFFSET SOURCE_INTEGER
  1566.                CALL    GET_INTEGER
  1567.                MOV     BX,DX
  1568.                MOV     DI,OFFSET SOURCE_DECIMAL
  1569.                CALL    GET_DECIMAL
  1570.  
  1571.                MOV     DI,CS:DESTINATION
  1572.                ADD     DI,CS:SORT_INDEX
  1573.                MOV     AX,CS:INDEX_SEG
  1574.                CMP     CS:TEMP_FLAG,1
  1575.                JNZ     GOT_LINE_SEG
  1576.                MOV     AX,CS
  1577. GOT_LINE_SEG:  MOV     DS,AX
  1578.                MOV     CX,TEXT_LEN[DI]
  1579.                MOV     SI,OFF_PTR[DI]
  1580.                MOV     DS,SEG_PTR[DI]
  1581.  
  1582.                MOV     DI,OFFSET DESTINATION_INTEGER
  1583.                CALL    GET_INTEGER
  1584.                MOV     DI,OFFSET DESTINATION_DECIMAL
  1585.                CALL    GET_DECIMAL
  1586.  
  1587.                MOV     AX,CS
  1588.                MOV     DS,AX
  1589.  
  1590.                MOV     SI,OFFSET SOURCE_INTEGER
  1591.                MOV     DI,OFFSET DESTINATION_INTEGER
  1592.                CMPSB
  1593.                JNZ     LINE_JMPN1
  1594.                XOR     AL,AL
  1595.                CMP     BYTE PTR [SI-1],PLUS_SIGN
  1596.                JZ      LINE_SIZE
  1597.                INC     AL
  1598.                XCHG    BX,DX
  1599.                XCHG    SI,DI
  1600. LINE_SIZE:     CMP     BX,DX
  1601. LINE_JMPN1:    JB      NO_LINE_SWAPN
  1602.                JZ      LINE_INTEGER
  1603.                JMP     SHORT LINE_SWAPN
  1604.  
  1605. LINE_INTEGER:  OR      DX,DX
  1606.                JZ      LINE_DECIMAL
  1607. NEXT_INT_CMP:  CMPSB
  1608. LINE_JMPN2:    JB      NO_LINE_SWAPN
  1609.                JZ      LOOP_INT
  1610.                JMP     SHORT LINE_SWAPN
  1611. LOOP_INT:      DEC     DX
  1612.                JNZ     NEXT_INT_CMP
  1613.  
  1614. LINE_DECIMAL:  MOV     SI,OFFSET SOURCE_DECIMAL
  1615.                MOV     DI,OFFSET DESTINATION_DECIMAL
  1616.                OR      AL,AL
  1617.                JZ      NEXT_DEC_CMP
  1618.                XCHG    SI,DI
  1619. NEXT_DEC_CMP:  LODSB
  1620.                SCASB
  1621. LINE_JMPN3:    JB      NO_LINE_SWAPN
  1622.                JZ      CK_LINE_NULL
  1623.                JMP     SHORT LINE_SWAPN
  1624. CK_LINE_NULL:  OR      AL,AL
  1625.                JNZ     NEXT_DEC_CMP
  1626.                JMP     SHORT NO_LINE_SWAPN
  1627.                 
  1628. LINE_SWAPN:    CMP     TEMP_FLAG,1
  1629.                JZ      CK_LINE_SWAPN
  1630.                MOV     TEMP_FLAG,1
  1631.                MOV     SI,DESTINATION
  1632.                MOV     DI,OFFSET TEMP_RECORD
  1633.                MOV     DESTINATION,DI
  1634.                MOV     CX,INDEX_PER_REC
  1635.                MOV     DS,INDEX_SEG
  1636.                MOV     AX,CS
  1637.                MOV     ES,AX
  1638.                REP     MOVSB
  1639.  
  1640. CK_LINE_SWAPN: MOV     AX,CS:INDEX_SEG
  1641.                MOV     DS,AX
  1642.                MOV     ES,AX
  1643.                MOV     SI,CS:SOURCE
  1644.                MOV     DI,SI
  1645.                MOV     CX,CS:INDEX_PER_REC
  1646.                MOV     AX,CX
  1647.                ADD     DI,CX
  1648.                REP     MOVSB
  1649.  
  1650.                SUB     CS:SOURCE,AX
  1651.                JS      NO_LINE_SWAPN
  1652.                JMP     NEXT_LINE_RECN
  1653.  
  1654. NO_LINE_SWAPN: MOV     AX,CS
  1655.                MOV     DS,AX
  1656.                CMP     TEMP_FLAG,1
  1657.                JNZ     NO_LINSERTN
  1658.                MOV     SI,OFFSET TEMP_RECORD
  1659.                MOV     ES,INDEX_SEG
  1660.                MOV     DI,SOURCE
  1661.                MOV     CX,INDEX_PER_REC
  1662.                ADD     DI,CX
  1663.                REP     MOVSB
  1664.  
  1665. NO_LINSERTN:   POP     DI
  1666.                POP     SI
  1667.                MOV     AX,INDEX_PER_REC
  1668.                ADD     SI,AX
  1669.                ADD     DI,AX
  1670.                JMP     NEXT_SLINEN
  1671.  
  1672. SORT_LINE_ENDN:POP     ES
  1673.                POP     DS
  1674.                RET
  1675.  
  1676. ;----------------------------------------------;
  1677. SORT_BLOCK_N:  PUSH    DS
  1678.                PUSH    ES
  1679.  
  1680.                MOV     BYTE PTR BLOCK_JMPN1,AL
  1681.                MOV     BYTE PTR BLOCK_JMPN2,AL
  1682.                MOV     BYTE PTR BLOCK_JMPN3,AL
  1683.                CMP     KEYS.BLOCK_BEG,INACTIVE
  1684.                JNZ     DO_SORT_BLKN
  1685.                JMP     SORT_BLK_ENDN
  1686.  
  1687. DO_SORT_BLKN:  MOV     MODIFY_FLAG,1
  1688.                MOV     AX,KEYS.BLOCK_INDEX[BP]
  1689.                CALL    CALC_ROW
  1690.                MOV     SORT_INDEX,AX
  1691.  
  1692.                XOR     SI,SI                   ;Source INDEX pointer.
  1693.                MOV     DI,INDEX_PER_REC        ;Destination INDEX pointer.
  1694.  
  1695. NEXT_BLKN:     MOV     AX,40H
  1696.                MOV     ES,AX
  1697.                MOV     AX,ES:[1AH]
  1698.                CMP     AX,ES:[1CH]
  1699.                JZ      CK_BLK_DONEN
  1700.                CALL    GETKEY
  1701.                JNC     CK_BLK_DONEN
  1702.                JMP     SORT_BLK_ENDN
  1703.  
  1704. CK_BLK_DONEN:  MOV     AX,DI
  1705.                ADD     AX,INDEX_PER_REC
  1706.                SUB     AX,SIZE INDEX_REC
  1707.                CMP     AX,LAST_LINE
  1708.                JBE     DO_BLK_SORTN
  1709.                JMP     SORT_BLK_ENDN
  1710.  
  1711. DO_BLK_SORTN:  PUSH    SI
  1712.                PUSH    DI
  1713.                MOV     SOURCE,SI
  1714.                MOV     DESTINATION,DI
  1715.                MOV     TEMP_FLAG,0
  1716.  
  1717. NEXT_BLK_RECN: MOV     DI,CS:SOURCE
  1718.                ADD     DI,CS:SORT_INDEX
  1719.                MOV     DS,CS:INDEX_SEG
  1720.                MOV     CX,TEXT_LEN[DI]
  1721.                MOV     SI,OFF_PTR[DI]
  1722.                MOV     DS,SEG_PTR[DI]
  1723.  
  1724.                MOV     AX,CS:KEYS.BLOCK_BEG[BP]
  1725.                ADD     SI,AX
  1726.                SUB     CX,AX
  1727.                JNS     BLK_SOURCE1
  1728.                XOR     CX,CX
  1729.  
  1730. BLK_SOURCE1:   MOV     AX,CS:KEYS.BLOCK_LEN[BP]
  1731.                CMP     CX,AX
  1732.                JB      BLK_SOURCE2
  1733.                MOV     CX,AX
  1734.  
  1735. BLK_SOURCE2:   MOV     AX,CS
  1736.                MOV     ES,AX
  1737.                MOV     DI,OFFSET SOURCE_INTEGER
  1738.                CALL    GET_INTEGER
  1739.                MOV     BX,DX
  1740.                MOV     DI,OFFSET SOURCE_DECIMAL
  1741.                CALL    GET_DECIMAL
  1742.  
  1743.                MOV     DI,CS:DESTINATION
  1744.                ADD     DI,CS:SORT_INDEX
  1745.                MOV     AX,CS:INDEX_SEG
  1746.                CMP     CS:TEMP_FLAG,1
  1747.                JNZ     GOT_BLK_SEG
  1748.                MOV     AX,CS
  1749. GOT_BLK_SEG:   MOV     DS,AX
  1750.                MOV     CX,TEXT_LEN[DI]
  1751.                MOV     SI,OFF_PTR[DI]
  1752.                MOV     DS,SEG_PTR[DI]
  1753.  
  1754.                MOV     AX,CS:KEYS.BLOCK_BEG[BP]
  1755.                ADD     SI,AX
  1756.                SUB     CX,AX
  1757.                JNS     BLK_DEST1
  1758.                XOR     CX,CX
  1759.  
  1760. BLK_DEST1:     MOV     AX,CS:KEYS.BLOCK_LEN[BP]
  1761.                CMP     CX,AX
  1762.                JB      BLK_DEST2
  1763.                MOV     CX,AX
  1764.  
  1765. BLK_DEST2:     MOV     DI,OFFSET DESTINATION_INTEGER
  1766.                CALL    GET_INTEGER
  1767.                MOV     DI,OFFSET DESTINATION_DECIMAL
  1768.                CALL    GET_DECIMAL
  1769.  
  1770.                MOV     AX,CS
  1771.                MOV     DS,AX
  1772.  
  1773.                MOV     SI,OFFSET SOURCE_INTEGER
  1774.                MOV     DI,OFFSET DESTINATION_INTEGER
  1775.                CMPSB
  1776.                JNZ     BLOCK_JMPN1
  1777.                XOR     AL,AL
  1778.                CMP     BYTE PTR [SI-1],PLUS_SIGN
  1779.                JZ      BLOCK_SIZE
  1780.                INC     AL
  1781.                XCHG    BX,DX
  1782.                XCHG    SI,DI
  1783. BLOCK_SIZE:    CMP     BX,DX
  1784. BLOCK_JMPN1:   JB      NO_BLK_SWAPN
  1785.                JZ      BLK_INTEGER
  1786.                JMP     SHORT BLK_SWAPN
  1787.  
  1788. BLK_INTEGER:   OR      DX,DX
  1789.                JZ      BLK_DECIMAL
  1790. NEXT_BLK_CMP:  CMPSB
  1791. BLOCK_JMPN2:   JB      NO_BLK_SWAPN
  1792.                JZ      LOOP_BLK
  1793.                JMP     SHORT BLK_SWAPN
  1794. LOOP_BLK:      DEC     DX
  1795.                JNZ     NEXT_BLK_CMP
  1796.  
  1797. BLK_DECIMAL:   MOV     SI,OFFSET SOURCE_DECIMAL
  1798.                MOV     DI,OFFSET DESTINATION_DECIMAL
  1799.                OR      AL,AL
  1800.                JZ      NEXT_BLK_CMP2
  1801.                XCHG    SI,DI
  1802. NEXT_BLK_CMP2: LODSB
  1803.                SCASB
  1804. BLOCK_JMPN3:   JB      NO_BLK_SWAPN
  1805.                JZ      CK_BLK_NULL
  1806.                JMP     SHORT BLK_SWAPN
  1807. CK_BLK_NULL:   OR      AL,AL
  1808.                JNZ     NEXT_BLK_CMP2
  1809.                JMP     SHORT NO_BLK_SWAPN
  1810.  
  1811. BLK_SWAPN:     CMP     TEMP_FLAG,1
  1812.                JZ      CK_BLK_SWAPN
  1813.                MOV     TEMP_FLAG,1
  1814.                MOV     SI,DESTINATION
  1815.                MOV     DI,OFFSET TEMP_RECORD
  1816.                MOV     DESTINATION,DI
  1817.                MOV     CX,INDEX_PER_REC
  1818.                MOV     DS,INDEX_SEG
  1819.                MOV     AX,CS
  1820.                MOV     ES,AX
  1821.                REP     MOVSB
  1822.  
  1823. CK_BLK_SWAPN:  MOV     AX,CS:INDEX_SEG
  1824.                MOV     DS,AX
  1825.                MOV     ES,AX
  1826.                MOV     SI,CS:SOURCE
  1827.                MOV     DI,SI
  1828.                MOV     CX,CS:INDEX_PER_REC
  1829.                MOV     AX,CX
  1830.                ADD     DI,CX
  1831.                REP     MOVSB
  1832.  
  1833.                SUB     CS:SOURCE,AX
  1834.                JS      NO_BLK_SWAPN
  1835.                JMP     NEXT_BLK_RECN
  1836.  
  1837. NO_BLK_SWAPN:  MOV     AX,CS
  1838.                MOV     DS,AX
  1839.                CMP     TEMP_FLAG,1
  1840.                JNZ     NO_BINSERTN
  1841.                MOV     SI,OFFSET TEMP_RECORD
  1842.                MOV     ES,INDEX_SEG
  1843.                MOV     DI,SOURCE
  1844.                MOV     CX,INDEX_PER_REC
  1845.                ADD     DI,CX
  1846.                REP     MOVSB
  1847.  
  1848. NO_BINSERTN:   POP     DI
  1849.                POP     SI
  1850.                MOV     AX,INDEX_PER_REC
  1851.                ADD     SI,AX
  1852.                ADD     DI,AX
  1853.                JMP     NEXT_BLKN
  1854.  
  1855. SORT_BLK_ENDN: POP     ES
  1856.                POP     DS
  1857.                RET
  1858.  
  1859. ;----------------------------------------------;
  1860. SORT_WORD_N:   PUSH    DS
  1861.                PUSH    ES
  1862.  
  1863.                MOV     BYTE PTR WORD_JMPN1,AL
  1864.                MOV     BYTE PTR WORD_JMPN2,AL
  1865.                MOV     BYTE PTR WORD_JMPN3,AL
  1866.                MOV     MODIFY_FLAG,1
  1867.  
  1868.                XOR     SI,SI
  1869.                MOV     DI,INDEX_PER_REC
  1870.  
  1871. NEXT_WLINEN:   MOV     AX,40H
  1872.                MOV     ES,AX
  1873.                MOV     AX,ES:[1AH]
  1874.                CMP     AX,ES:[1CH]
  1875.                JZ      CK_WORD_DONEN
  1876.                CALL    GETKEY
  1877.                JNC     CK_WORD_DONEN
  1878.                JMP     SORT_WORD_ENDN
  1879.  
  1880. CK_WORD_DONEN: MOV     AX,DI
  1881.                ADD     AX,INDEX_PER_REC
  1882.                SUB     AX,SIZE INDEX_REC
  1883.                CMP     AX,LAST_LINE
  1884.                JBE     DO_WORD_SORTN
  1885.                JMP     SORT_WORD_ENDN
  1886.  
  1887. DO_WORD_SORTN: PUSH    SI
  1888.                PUSH    DI
  1889.                MOV     SOURCE,SI
  1890.                MOV     DESTINATION,DI
  1891.                MOV     TEMP_FLAG,0
  1892.  
  1893. NEXT_WORD_RECN:MOV     ES,CS:INDEX_SEG
  1894.                MOV     BX,CS:SOURCE
  1895.                CALL    WORD_ADDRESS
  1896.                JC      WORD_SOURCE
  1897.                MOV     CX,SI
  1898.                SUB     CX,DI
  1899.                INC     CX
  1900.  
  1901. WORD_SOURCE:   MOV     SI,DI
  1902.                MOV     AX,CS
  1903.                MOV     ES,AX
  1904.                MOV     DI,OFFSET SOURCE_INTEGER
  1905.                CALL    GET_INTEGER
  1906.                PUSH    DX
  1907.                MOV     DI,OFFSET SOURCE_DECIMAL
  1908.                CALL    GET_DECIMAL
  1909.  
  1910.                MOV     AX,CS:INDEX_SEG
  1911.                CMP     CS:TEMP_FLAG,1
  1912.                JNZ     GET_DEST_WORDN
  1913.                MOV     AX,CS
  1914. GET_DEST_WORDN:MOV     ES,AX
  1915.                MOV     BX,CS:DESTINATION
  1916.                CALL    WORD_ADDRESS
  1917.                JC      WORD_DEST
  1918.                MOV     CX,SI
  1919.                SUB     CX,DI
  1920.                INC     CX
  1921.  
  1922. WORD_DEST:     MOV     SI,DI
  1923.                MOV     AX,CS
  1924.                MOV     ES,AX
  1925.                MOV     DI,OFFSET DESTINATION_INTEGER
  1926.                CALL    GET_INTEGER
  1927.                MOV     DI,OFFSET DESTINATION_DECIMAL
  1928.                CALL    GET_DECIMAL
  1929.  
  1930.                MOV     AX,CS
  1931.                MOV     DS,AX
  1932.  
  1933.                POP     BX
  1934.                MOV     SI,OFFSET SOURCE_INTEGER
  1935.                MOV     DI,OFFSET DESTINATION_INTEGER
  1936.                CMPSB
  1937.                JNZ     WORD_JMPN1
  1938.                XOR     AL,AL
  1939.                CMP     BYTE PTR [SI-1],PLUS_SIGN
  1940.                JZ      WORD_SIZE
  1941.                INC     AL
  1942.                XCHG    BX,DX
  1943.                XCHG    SI,DI
  1944. WORD_SIZE:     CMP     BX,DX
  1945. WORD_JMPN1:    JB      NO_WORD_SWAPN
  1946.                JZ      WORD_INTEGER
  1947.                JMP     SHORT WORD_SWAPN
  1948.  
  1949. WORD_INTEGER:  OR      DX,DX
  1950.                JZ      WORD_DECIMAL
  1951. NEXT_WORD_CMP: CMPSB
  1952. WORD_JMPN2:    JB      NO_WORD_SWAPN
  1953.                JZ      LOOP_WORD
  1954.                JMP     SHORT WORD_SWAPN
  1955. LOOP_WORD:     DEC     DX
  1956.                JNZ     NEXT_WORD_CMP
  1957.  
  1958. WORD_DECIMAL:  MOV     SI,OFFSET SOURCE_DECIMAL
  1959.                MOV     DI,OFFSET DESTINATION_DECIMAL
  1960.                OR      AL,AL
  1961.                JZ      NEXT_WORD_CMP2
  1962.                XCHG    SI,DI
  1963. NEXT_WORD_CMP2:LODSB
  1964.                SCASB
  1965. WORD_JMPN3:    JB      NO_WORD_SWAPN
  1966.                JZ      CK_WORD_NULL
  1967.                JMP     SHORT WORD_SWAPN
  1968. CK_WORD_NULL:  OR      AL,AL
  1969.                JNZ     NEXT_WORD_CMP2
  1970.                JMP     SHORT NO_WORD_SWAPN
  1971.  
  1972. WORD_SWAPN:    CMP     TEMP_FLAG,1
  1973.                JZ      CK_WORD_SWAPN
  1974.                MOV     TEMP_FLAG,1
  1975.                MOV     SI,DESTINATION
  1976.                MOV     DI,OFFSET TEMP_RECORD
  1977.                MOV     DESTINATION,DI
  1978.                MOV     CX,INDEX_PER_REC
  1979.                MOV     DS,INDEX_SEG
  1980.                MOV     AX,CS
  1981.                MOV     ES,AX
  1982.                REP     MOVSB
  1983.  
  1984. CK_WORD_SWAPN: MOV     AX,CS:INDEX_SEG
  1985.                MOV     DS,AX
  1986.                MOV     ES,AX
  1987.                MOV     SI,CS:SOURCE
  1988.                MOV     DI,SI
  1989.                MOV     CX,CS:INDEX_PER_REC
  1990.                MOV     AX,CX
  1991.                ADD     DI,CX
  1992.                REP     MOVSB
  1993.  
  1994.                SUB     CS:SOURCE,AX
  1995.                JS      NO_WORD_SWAPN
  1996.                JMP     NEXT_WORD_RECN
  1997.  
  1998. NO_WORD_SWAPN: MOV     AX,CS
  1999.                MOV     DS,AX
  2000.                CMP     TEMP_FLAG,1
  2001.                JNZ     NO_WINSERTN
  2002.                MOV     SI,OFFSET TEMP_RECORD
  2003.                MOV     ES,INDEX_SEG
  2004.                MOV     DI,SOURCE
  2005.                MOV     CX,INDEX_PER_REC
  2006.                ADD     DI,CX
  2007.                REP     MOVSB
  2008.  
  2009. NO_WINSERTN:   POP     DI
  2010.                POP     SI
  2011.                MOV     AX,INDEX_PER_REC
  2012.                ADD     SI,AX
  2013.                ADD     DI,AX
  2014.                JMP     NEXT_WLINEN
  2015.  
  2016. SORT_WORD_ENDN:POP     ES
  2017.                POP     DS
  2018.                RET
  2019.  
  2020. ;----------------------------------------------;
  2021. ; INPUT:  DS:SI -> string; ES:DI-> Storage; CX=text length;
  2022. ; OUTPUT: DX=integer length.
  2023.  
  2024. GET_INTEGER:   XOR     DX,DX
  2025.                MOV     AH,MINUS_SIGN
  2026.                MOV     AL,PLUS_SIGN
  2027.                STOSB
  2028.                JCXZ    INTEGER_END
  2029. NEXT_INTEGER:  LODSB
  2030.                CMP     AL,DECIMAL_POINT
  2031.                JZ      INTEGER_DONE
  2032.                CMP     AL,AH
  2033.                JZ      STORE_NEGATIVE
  2034.                CMP     AL,"0"
  2035.                JB      LOOP_INTEGER
  2036.                CMP     AL,"9"
  2037.                JA      LOOP_INTEGER
  2038.                STOSB
  2039.                XOR     AH,AH
  2040.                INC     DX
  2041. LOOP_INTEGER:  LOOP    NEXT_INTEGER
  2042.                INC     CX
  2043. INTEGER_DONE:  DEC     CX
  2044. INTEGER_END:   RET
  2045.  
  2046. STORE_NEGATIVE:XOR     AH,AH
  2047.                MOV     BYTE PTR ES:[DI-1],AH
  2048.                JMP     LOOP_INTEGER
  2049.  
  2050. ;----------------------------------------------;
  2051. ; INPUT: DI-> Storage; CX=text length; OUTPUT: NULL terminated.
  2052. GET_DECIMAL:   JCXZ    DEC_END
  2053. NEXT_DEC:      LODSB
  2054.                CMP     AL,"0"
  2055.                JB      DEC_DONE
  2056.                CMP     AL,"9"
  2057.                JA      DEC_DONE
  2058.                STOSB
  2059.                LOOP    NEXT_DEC
  2060.                INC     CX
  2061. DEC_DONE:      DEC     CX
  2062. DEC_END:       XOR     AL,AL
  2063.                STOSB
  2064.                RET
  2065.  
  2066. ;----------------------------------------------;
  2067. SH_LINE_REC:   MOV     AL,-1
  2068.                JMP     SHORT DO_LINES_REC
  2069.  
  2070. LINES_REC:     MOV     AL,1
  2071. DO_LINES_REC:  MOV     BL,LINES_PER_REC
  2072.                ADD     BL,AL
  2073.                JNS     CK_LINES_REC
  2074.                MOV     BL,LINES_REC_MAX - 1
  2075. CK_LINES_REC:  CMP     BL,LINES_REC_MAX
  2076.                JB      LINES_REC_END
  2077.                XOR     BL,BL
  2078. LINES_REC_END: MOV     LINES_PER_REC,BL
  2079.                INC     BL
  2080.                MOV     AL,SIZE INDEX_REC
  2081.                MUL     BL
  2082.                MOV     INDEX_PER_REC,AX
  2083.                RET
  2084.  
  2085. ;----------------------------------------------;
  2086. SH_PRIORITY:   MOV     AL,-1
  2087.                JMP     SHORT DO_PRIORITY
  2088.  
  2089. PRIORITY:      MOV     AL,1
  2090. DO_PRIORITY:   MOV     BL,CURRENT_KEY
  2091.                ADD     BL,AL
  2092.                JNS     CK_PRIORITY
  2093.                MOV     BL,KEY_MAX - 1
  2094. CK_PRIORITY:   CMP     BL,KEY_MAX
  2095.                JB      PRIORITY_END
  2096.                XOR     BL,BL
  2097. PRIORITY_END:  MOV     CURRENT_KEY,BL
  2098.                RET
  2099.  
  2100. ;----------------------------------------------;
  2101. DIRECTION:     CALL    GET_PRIORITY
  2102.                XOR     KEYS.SORT_DIRECTION[BP],1
  2103.                RET
  2104.  
  2105. ;----------------------------------------------;
  2106. SORT_TYPE:     CALL    GET_PRIORITY
  2107.                XOR     KEYS.KEY_TYPE[BP],1
  2108.                RET
  2109.  
  2110. ;----------------------------------------------;
  2111. SH_FIELD_TYPE: MOV     AL,-1
  2112.                JMP     SHORT DO_FIELD
  2113.  
  2114. FIELD_TYPE:    MOV     AL,1
  2115. DO_FIELD:      CALL    GET_PRIORITY
  2116.                MOV     BL,KEYS.KEY_FIELD[BP]
  2117.                ADD     BL,AL
  2118.                JNS     CK_FIELD
  2119.                MOV     BL,LINE_TYPE
  2120. CK_FIELD:      CMP     BL,LINE_TYPE
  2121.                JBE     FIELD_END
  2122.                XOR     BL,BL
  2123. FIELD_END:     MOV     KEYS.KEY_FIELD[BP],BL
  2124.                RET
  2125.  
  2126. ;----------------------------------------------;
  2127. SH_BLOCKSTART: MOV     AL,-1
  2128.                JMP     SHORT DO_BLOCKSTART
  2129.  
  2130. BLOCKSTART:    MOV     AL,1
  2131. DO_BLOCKSTART: CALL    GET_PRIORITY
  2132.                MOV     BL,KEYS.KEY_FIELD[BP]
  2133.                CMP     BL,BLOCK_TYPE
  2134.                JNZ     CK_LINE
  2135.  
  2136.                CALL    MARK_BLOCK
  2137.                JMP     SHORT BLOCKEND
  2138.  
  2139.  
  2140. CK_LINE:       CMP     BL,LINE_TYPE
  2141.                JNZ     CK_WORD
  2142.                MOV     AL,CURSOR_ROW
  2143.                XOR     AH,AH
  2144.                MOV     CL,SIZE INDEX_REC
  2145.                MUL     CL
  2146.                ADD     AX,TOP_LINE
  2147.                MOV     KEYS.LINE_INDEX[BP],AX
  2148.                JMP     SHORT BLOCKEND
  2149.  
  2150.  
  2151. CK_WORD:       CMP     BL,WORD_TYPE
  2152.                JNZ     BLOCKEND
  2153.                MOV     BL,KEYS.WORD_POS[BP]
  2154. SKIP_ZERO:     ADD     BL,AL
  2155.                OR      BL,BL
  2156.                JZ      SKIP_ZERO
  2157.                CMP     BL,9
  2158.                JLE     CK_LOW
  2159.                MOV     BL,-9
  2160. CK_LOW:        CMP     BL,-9
  2161.                JGE     STORE_WORD
  2162.                MOV     BL,9
  2163. STORE_WORD:    MOV     KEYS.WORD_POS[BP],BL
  2164.  
  2165. BLOCKEND:      RET
  2166.  
  2167. ;---------------
  2168. LAST_COLUMN    DW      ?
  2169.  
  2170. MARK_BLOCK:    CALL    MENU_OFFSET
  2171.                ADD     DI,CRT_WIDTH
  2172.                ADD     DI,2 * 56
  2173.                MOV     SI,OFFSET END_MSG
  2174.                MOV     BH,COLOR.B
  2175.                CALL    WRITE_STRING
  2176.  
  2177.                MOV     AL,SIZE INDEX_REC
  2178.                MUL     CURSOR_ROW
  2179.                ADD     AX,TOP_LINE
  2180.                MOV     MARK_INDEX,AX
  2181.  
  2182.                MOV     AL,CURSOR_COLUMN
  2183.                XOR     AH,AH
  2184.                ADD     AX,START_COLUMN
  2185.                MOV     MARK_LEFT,AX
  2186.                MOV     MARK_RIGHT,AX
  2187.                MOV     LAST_COLUMN,AX
  2188.  
  2189. NEXT_MARK:     MOV     AL,CURSOR_COLUMN
  2190.                XOR     AH,AH
  2191.                MOV     BX,LAST_COLUMN
  2192.                MOV     LAST_COLUMN,AX
  2193.                CMP     AX,MARK_LEFT
  2194.                JB      STORE_LEFT
  2195.                CMP     AX,MARK_RIGHT
  2196.                JA      STORE_RIGHT
  2197.                CMP     AX,BX
  2198.                JA      STORE_LEFT
  2199. STORE_RIGHT:   MOV     MARK_RIGHT,AX
  2200.                JMP     SHORT UPDATE_IT
  2201. STORE_LEFT:    MOV     MARK_LEFT,AX
  2202.  
  2203. UPDATE_IT:     CALL    UPDATE_TEXT
  2204.  
  2205.                CALL    CLEAR_KEY
  2206.                CALL    GETKEY
  2207.                JC      MARKBLOCK_END
  2208.                CMP     AL,LEFT_SCAN
  2209.                JNZ     CK_MARK_RIGHT
  2210.                CALL    LEFT
  2211.                JMP     NEXT_MARK
  2212.  
  2213. CK_MARK_RIGHT: CMP     AL,RIGHT_SCAN
  2214.                JNZ     CK_F10
  2215.                CALL    RIGHT
  2216.                JMP     NEXT_MARK
  2217.  
  2218. CK_F10:        CMP     AL,F10_SCAN
  2219.                JZ      GOT_MARK
  2220.                CMP     AH,CR
  2221.                JNZ     NEXT_MARK
  2222.  
  2223. GOT_MARK:      MOV     AX,MARK_INDEX
  2224.                MOV     KEYS.BLOCK_INDEX[BP],AX
  2225.                MOV     AX,MARK_LEFT
  2226.                MOV     KEYS.BLOCK_BEG[BP],AX
  2227.                MOV     BX,MARK_RIGHT
  2228.                SUB     BX,AX
  2229.                INC     BX
  2230.                MOV     KEYS.BLOCK_LEN[BP],BX
  2231.  
  2232. MARKBLOCK_END: RET
  2233.  
  2234. ;----------------------------------------------;
  2235. RESET:         MOV     CURRENT_KEY,KEY_MAX - 1
  2236. NEXT_RESET:    CALL    GET_PRIORITY
  2237.                MOV     KEYS.SORT_DIRECTION[BP],ASCEND
  2238.                MOV     KEYS.KEY_TYPE[BP],ALPHA_TYPE
  2239.                MOV     KEYS.KEY_FIELD[BP],NONE_TYPE
  2240.                MOV     KEYS.BLOCK_INDEX[BP],0
  2241.                MOV     KEYS.BLOCK_BEG[BP],INACTIVE
  2242.                MOV     KEYS.WORD_POS[BP],1
  2243.                MOV     KEYS.LINE_INDEX[BP],0
  2244.                DEC     CURRENT_KEY
  2245.                JNS     NEXT_RESET
  2246.  
  2247.                MOV     LINES_PER_REC,0
  2248.                MOV     INDEX_PER_REC,SIZE INDEX_REC
  2249.                MOV     CURRENT_KEY,0
  2250.                RET
  2251.  
  2252. ;----------------------------------------------;
  2253. HELP_ROW       EQU     6
  2254. HELP_COL       EQU     2 * 8
  2255. HELP_WIDTH     EQU     62
  2256. HELP_HEADING   LABEL   BYTE
  2257. DB   "║ Priority   Field   Field ID      Direction    Type         ║",0
  2258. HELP_MSG       LABEL   BYTE
  2259. DB   "║ Press Alt F1 to reset.  Any other key to continue.         ║",0
  2260.  
  2261. HELP:          CALL    HIDE_CURSOR
  2262.                MOV     AX,HELP_ROW
  2263.                CALL    CALC_ADDR
  2264.                ADD     DI,HELP_COL
  2265.                MOV     BH,COLOR.B
  2266.  
  2267.                PUSH    DI
  2268.                MOV     AL,"╔"
  2269.                CALL    WRITE_SCREEN
  2270.                MOV     AL,"═"
  2271.                MOV     CX,HELP_WIDTH - 2
  2272.                CALL    REPEAT_CHAR
  2273.                MOV     AL,"╗"
  2274.                CALL    WRITE_SCREEN
  2275.                POP     DI
  2276.                ADD     DI,CRT_WIDTH
  2277.  
  2278.                PUSH    DI
  2279.                MOV     SI,OFFSET HELP_HEADING
  2280.                CALL    WRITE_STRING
  2281.                POP     DI
  2282.                ADD     DI,CRT_WIDTH
  2283.  
  2284.                MOV     BP,KEY_MAX
  2285. NEXT_HELP:     PUSH    DI
  2286.                MOV     AL,"║"
  2287.                CALL    WRITE_SCREEN
  2288.                MOV     AL,SPACE
  2289.                MOV     CX,HELP_WIDTH - 2
  2290.                CALL    REPEAT_CHAR
  2291.                MOV     AL,"║"
  2292.                CALL    WRITE_SCREEN
  2293.                POP     DI
  2294.                ADD     DI,CRT_WIDTH
  2295.                DEC     BP
  2296.                JNZ     NEXT_HELP
  2297.  
  2298.                PUSH    DI
  2299.                MOV     SI,OFFSET HELP_MSG
  2300.                CALL    WRITE_STRING
  2301.                POP     DI
  2302.                ADD     DI,CRT_WIDTH
  2303.                MOV     AL,"╚"
  2304.                CALL    WRITE_SCREEN
  2305.                MOV     AL,"═"
  2306.                MOV     CX,HELP_WIDTH - 2
  2307.                CALL    REPEAT_CHAR
  2308.                MOV     AL,"╝"
  2309.                CALL    WRITE_SCREEN
  2310.  
  2311. ;--------------------
  2312.  
  2313.                MOV     AX,HELP_ROW + 2
  2314.                CALL    CALC_ADDR
  2315.                ADD     DI,HELP_COL + (2 * 5)
  2316.                PUSH    WORD PTR CURRENT_KEY
  2317.                MOV     CURRENT_KEY,0
  2318.  
  2319. NEXT_HELP2:    PUSH    DI
  2320.                MOV     AL,CURRENT_KEY
  2321.                ADD     AL,"1"
  2322.                CALL    WRITE_SCREEN
  2323.  
  2324.                CALL    GET_PRIORITY
  2325.  
  2326.                ADD     DI,2 * 7
  2327.                CALL    DISP_TYPE
  2328.                CMP     CL,NONE_TYPE
  2329.                JZ      LOOP_HELP
  2330.  
  2331.                ADD     DI,2 * 3
  2332.                PUSH    DI
  2333.                CMP     CL,LINE_TYPE
  2334.                JNZ     CK_HELP_BLK
  2335.                CALL    DISP_LINE
  2336.                JMP     SHORT HELP_TYPE_DONE
  2337. CK_HELP_BLK:   CMP     CL,BLOCK_TYPE
  2338.                JNZ     DO_HELP_WORD
  2339.                CALL    DISP_BLOCK
  2340.                JMP     SHORT HELP_TYPE_DONE
  2341. DO_HELP_WORD:  CALL    DISP_WORD
  2342. HELP_TYPE_DONE:POP     DI
  2343.  
  2344.                ADD     DI,2 * 13
  2345.                PUSH    DI
  2346.                ADD     DI,2
  2347.                CALL    DISP_ASCEND
  2348.                POP     DI
  2349.  
  2350.                ADD     DI,2 * 14
  2351.                CALL    DISP_ALPHA
  2352.  
  2353. LOOP_HELP:     POP     DI
  2354.                ADD     DI,CRT_WIDTH
  2355.                INC     CURRENT_KEY
  2356.                CMP     CURRENT_KEY,KEY_MAX
  2357.                JB      NEXT_HELP2
  2358.  
  2359.                POP     WORD PTR CURRENT_KEY
  2360.  
  2361. ;--------------------
  2362.  
  2363.                CALL    GETKEY
  2364.                CMP     AL,ALT_F1
  2365.                JNZ     HELP_END
  2366.                CALL    RESET
  2367.                CALL    DISPLAY_MENU
  2368.                JMP     HELP
  2369.  
  2370. HELP_END:      RET
  2371.  
  2372. ;----------------------------------------------;
  2373. ; INPUT: DI=TOP_LINE, SI=Bottom offset, DX=Bottom cursor line; CX=SIZE INDEX_REC
  2374.  
  2375. UP:            MOV     AL,-1
  2376.                NEG     CX
  2377.                JMP     SHORT DO_UP_DN
  2378.  
  2379. DOWN:          MOV     AL,1
  2380.  
  2381. DO_UP_DN:      MOV     AH,CURSOR_ROW
  2382.                ADD     AH,AL
  2383.                JS      CK_PAGE
  2384.                CMP     AH,DL
  2385.                JA      CK_PAGE
  2386.                MOV     CURSOR_ROW,AH
  2387.                JMP     SHORT UP_DN_END
  2388.  
  2389. CK_PAGE:       ADD     DI,CX
  2390.                JS      UP_DN_END
  2391.                ADD     SI,CX
  2392.                CMP     SI,LAST_LINE
  2393.                JA      UP_DN_END
  2394.                MOV     TOP_LINE,DI
  2395. UP_DN_END:     RET
  2396.  
  2397. ;---------------;
  2398. PGUP:          NEG     CX
  2399.  
  2400. PGDN:          MOV     BP,DX
  2401.                MOV     AX,LISTING_LEN
  2402.                MUL     CX
  2403.                ADD     DI,AX
  2404.                JS      HOME_PAGE
  2405.                ADD     SI,AX
  2406.                CMP     SI,LAST_LINE
  2407.                JBE     PAGE_END
  2408.  
  2409.                MOV     DX,BP
  2410.                MOV     CURSOR_ROW,DL
  2411.                MOV     DI,LAST_LINE
  2412.                ADD     DI,SIZE INDEX_REC
  2413.                SUB     DI,AX
  2414.                JNS     PAGE_END
  2415.                XOR     DI,DI
  2416.                JMP     SHORT PAGE_END
  2417.  
  2418. HOME_PAGE:     XOR     DI,DI
  2419.                MOV     CURSOR_ROW,0
  2420. PAGE_END:      MOV     TOP_LINE,DI
  2421.                RET
  2422.  
  2423. ;---------------;
  2424. LEFT:          MOV     AX,-1
  2425.                JMP     SHORT DO_LEFT_RIGHT
  2426.  
  2427. RIGHT:         MOV     AX,1
  2428.  
  2429. DO_LEFT_RIGHT: MOV     BX,START_COLUMN
  2430.                MOV     DL,CURSOR_COLUMN
  2431.                MOV     CX,COLUMNS
  2432.                ADD     DL,AL
  2433.                JS      CK_COL
  2434.                CMP     DL,CL
  2435.                JAE     CK_COL
  2436.                MOV     CURSOR_COLUMN,DL
  2437.                JMP     SHORT LFT_RGT_END
  2438.  
  2439. CK_COL:        ADD     BX,AX
  2440.                JS      LFT_RGT_END
  2441.                ADD     CX,BX
  2442.                CMP     CX,LONGEST_LINE
  2443.                JA      LFT_RGT_END
  2444.                MOV     START_COLUMN,BX
  2445.  
  2446. LFT_RGT_END:   RET
  2447.  
  2448. ;---------------;
  2449. HOME_KEY:      CMP     CURSOR_COLUMN,0
  2450.                MOV     CURSOR_COLUMN,0
  2451.                MOV     START_COLUMN,0
  2452.                JNZ     HOME_END
  2453.                CMP     CURSOR_ROW,0
  2454.                MOV     CURSOR_ROW,0
  2455.                JNZ     HOME_END
  2456.                MOV     TOP_LINE,0
  2457. HOME_END:      RET
  2458.  
  2459. END_KEY:       MOV     AX,LONGEST_LINE
  2460.                DEC     AX
  2461.                MOV     BX,COLUMNS
  2462.                DEC     BX
  2463.                SUB     AX,BX
  2464.                JNS     GOT_END
  2465.                XOR     AX,AX
  2466. GOT_END:       CMP     START_COLUMN,AX
  2467.                MOV     START_COLUMN,AX
  2468.                JNZ     END_END
  2469.                CMP     CURSOR_COLUMN,BL
  2470.                JNZ     END_END
  2471.                CMP     CURSOR_ROW,DL
  2472.                MOV     CURSOR_ROW,DL
  2473.                JZ      CTRL_END
  2474. END_END:       MOV     CURSOR_COLUMN,BL
  2475.                RET
  2476.  
  2477. CTRL_HOME:     MOV     TOP_LINE,0
  2478.                MOV     CURSOR_ROW,0
  2479.                MOV     CURSOR_COLUMN,0
  2480.                MOV     START_COLUMN,0
  2481.                RET
  2482.  
  2483. CTRL_END:      MOV     AX,LONGEST_LINE
  2484.                MOV     BX,COLUMNS
  2485.                SUB     AX,BX
  2486.                JNS     GOT_END2
  2487.                XOR     AX,AX
  2488. GOT_END2:      MOV     START_COLUMN,AX
  2489.                DEC     BX
  2490.                MOV     CURSOR_COLUMN,BL
  2491.                MOV     CURSOR_ROW,DL
  2492.  
  2493.                MOV     AX,LISTING_LEN
  2494.                DEC     AX
  2495.                MUL     CX
  2496.                MOV     DI,LAST_LINE
  2497.                SUB     DI,AX
  2498.                JNB     CTRL_END_END
  2499.                XOR     DI,DI
  2500. CTRL_END_END:  MOV     TOP_LINE,DI
  2501.                RET
  2502.  
  2503. ;----------------------------------------------;
  2504. DISP_DISPLAY:  PUSH    DS
  2505.                PUSH    ES
  2506.                PUSH    BP
  2507.  
  2508.                MOV     BP,TOP_LINE
  2509.                MOV     ES,INDEX_SEG
  2510.                MOV     CX,LISTING_LEN
  2511.                MOV     DI,CRT_WIDTH
  2512.  
  2513. NEXT_DISP:     PUSH    CX
  2514.                PUSH    DI
  2515.                MOV     CX,CS:COLUMNS
  2516.                MOV     DS,ES:SEG_PTR[BP]
  2517.                MOV     SI,ES:OFF_PTR[BP]
  2518.                MOV     BX,ES:TEXT_LEN[BP]
  2519.  
  2520.                MOV     AX,CS:START_COLUMN
  2521.                MOV     CS:DISPLAY_COLUMN,AX
  2522.                ADD     SI,AX
  2523.                SUB     BX,AX
  2524.                JNC     NEXT_DISP2
  2525.                XOR     BX,BX
  2526.  
  2527. NEXT_DISP2:    MOV     CS:DISPLAY_TEXT,BX
  2528. NEXT_DISP3:    CMP     CS:DISPLAY_TEXT,0
  2529.                JZ      PAD_LINE
  2530.                CMP     BP,CS:LAST_LINE
  2531.                JA      PAD_LINE
  2532.  
  2533.                MOV     BH,CS:COLOR.W
  2534.                CMP     BP,CS:MARK_INDEX
  2535.                JNZ     GET_BYTE
  2536.                MOV     AX,CS:DISPLAY_COLUMN
  2537.                CMP     AX,CS:MARK_LEFT
  2538.                JB      GET_BYTE
  2539.                CMP     AX,CS:MARK_RIGHT
  2540.                JA      GET_BYTE
  2541.                MOV     BH,CS:COLOR.C
  2542.  
  2543. GET_BYTE:      LODSB
  2544.                CALL    WRITE_SCREEN
  2545.                DEC     CS:DISPLAY_TEXT
  2546.                INC     CS:DISPLAY_COLUMN
  2547.                LOOP    NEXT_DISP3
  2548.                JMP     SHORT DISPLAY_LOOP
  2549.  
  2550. PAD_LINE:      MOV     BH,CS:COLOR.W
  2551.                CMP     BP,CS:MARK_INDEX
  2552.                JNZ     WRITE_SPACE
  2553.                MOV     AX,CS:DISPLAY_COLUMN
  2554.                CMP     AX,CS:MARK_LEFT
  2555.                JB      WRITE_SPACE
  2556.                CMP     AX,CS:MARK_RIGHT
  2557.                JA      WRITE_SPACE
  2558.                MOV     BH,CS:COLOR.C
  2559.  
  2560. WRITE_SPACE:   MOV     AL,SPACE
  2561.                CALL    WRITE_SCREEN
  2562.                INC     CS:DISPLAY_COLUMN
  2563.                LOOP    PAD_LINE
  2564.  
  2565. DISPLAY_LOOP:  ADD     BP,SIZE INDEX_REC
  2566.                POP     DI
  2567.                ADD     DI,CS:CRT_WIDTH
  2568.                POP     CX
  2569.                DEC     CX
  2570.                JZ      DISPLAY_END
  2571.                JMP     NEXT_DISP
  2572.  
  2573. DISPLAY_END:   POP     BP
  2574.                POP     ES
  2575.                POP     DS
  2576.                RET
  2577.  
  2578. ;----------------------------------------------;
  2579. ; OUTPUT: CF=1 if failed;  SI-> Error message.
  2580.  
  2581. READ_FILE:     CALL    MENU_OFFSET
  2582.                MOV     BH,COLOR.B
  2583.                MOV     SI,OFFSET LOADING_FILE
  2584.                CALL    WRITE_STRING
  2585.  
  2586.                CALL    DOS_CURSOR
  2587.                MOV     DX,FILENAME
  2588.                MOV     AX,3D00H
  2589.                INT     21H
  2590.                MOV     SI,OFFSET FILE_NOT_FOUND
  2591.                JC      READ_FILE_END
  2592.                MOV     BX,AX
  2593.  
  2594. READ_FILE2:    PUSH    DS
  2595.                CMP     STDIN_FLAG,1
  2596.                JZ      READ_FILE3
  2597.  
  2598.                MOV     AX,4400H                ;Device info.
  2599.                INT     21H
  2600.                TEST    DX,10000000B
  2601.                JZ      READ_FILE3
  2602.                STC
  2603.                JMP     SHORT READ_CLOSE
  2604.  
  2605. READ_FILE3:    MOV     BP,TEXT_SEG
  2606.                JMP     SHORT NEXT_READ2
  2607.  
  2608. NEXT_READ:     ADD     BP,READ_SIZE SHR 4
  2609. NEXT_READ2:    CMP     BP,CS:MEM_TOP_SEG
  2610.                JA      READ_FULL
  2611.                MOV     CX,READ_SIZE
  2612.                JNZ     READ
  2613.                MOV     CX,CS:MEM_TOP_OFF
  2614. READ:          XOR     DX,DX
  2615.                MOV     DS,BP
  2616.                MOV     AH,3FH
  2617.                INT     21H
  2618.                MOV     SI,OFFSET READ_FAIL
  2619.                JC      READ_CLOSE
  2620.                OR      AX,AX
  2621.                JZ      READ_CLOSE
  2622.  
  2623.                CMP     AX,READ_SIZE
  2624.                JZ      NEXT_READ
  2625.                CMP     CX,AX
  2626.                JNZ     READ_CLOSE
  2627.  
  2628. READ_FULL:     MOV     SI,OFFSET NOT_ENOUGH
  2629.                STC
  2630.  
  2631. READ_CLOSE:    MOV     CS:EOF_SEG,BP
  2632.                MOV     CS:EOF_OFF,AX
  2633.                PUSHF
  2634.                MOV     AH,3EH
  2635.                INT     21H
  2636.                POPF
  2637.  
  2638.                POP     DS
  2639. READ_FILE_END: PUSHF
  2640.                CALL    CLEAR_KEY
  2641.                POPF
  2642.                RET
  2643.  
  2644. ;--------------------------------------------------------;
  2645. ; OUTPUT: CF=1 if too many lines;  SI-> Error message.
  2646.  
  2647. INDEX:         PUSH    DS
  2648.                PUSH    ES
  2649.                MOV     LONGEST_LINE,0
  2650.                MOV     BX,EOF_SEG
  2651.                MOV     DX,EOF_OFF
  2652.  
  2653.                MOV     ES,INDEX_SEG
  2654.                XOR     DI,DI
  2655.                MOV     BP,TEXT_SEG
  2656.                MOV     DS,BP
  2657.                XOR     SI,SI
  2658.  
  2659. NEXT_INDEX:    MOV     ES:OFF_PTR[DI],SI
  2660.                MOV     ES:SEG_PTR[DI],BP
  2661.                XOR     CX,CX                   ;Line length.
  2662.  
  2663. NEXT_BYTE:     CMP     SI,READ_SIZE
  2664.                JB      CK_END
  2665.                ADD     BP,READ_SIZE SHR 4
  2666.                MOV     DS,BP
  2667.                SUB     SI,READ_SIZE
  2668.  
  2669. CK_END:        CMP     SI,DX
  2670.                JNZ     READ_BYTE
  2671.                CMP     BP,BX
  2672.                JNZ     READ_BYTE
  2673.                OR      CX,CX
  2674.                JNZ     STORE_LAST
  2675.                SUB     DI,SIZE INDEX_REC
  2676.                JMP     SHORT INDEX_END
  2677. STORE_LAST:    MOV     ES:TEXT_LEN[DI],CX
  2678.                MOV     ES:LINE_LEN[DI],CX
  2679.                JMP     SHORT INDEX_END
  2680.  
  2681. READ_BYTE:     LODSB
  2682.                CMP     AL,CR
  2683.                JZ      LINE_END2
  2684.                CMP     AL,CTRL_Z
  2685.                JZ      NEXT_BYTE
  2686.                INC     CX
  2687.                CMP     CX,LINE_MAX
  2688.                JNZ     NEXT_BYTE
  2689.                MOV     SI,OFFSET LINE_TOO_LONG
  2690.                STC
  2691.                JMP     SHORT INDEX_END
  2692.  
  2693. LINE_END2:     MOV     ES:TEXT_LEN[DI],CX
  2694.                CMP     CX,CS:LONGEST_LINE
  2695.                JBE     CK_LEN
  2696.                MOV     CS:LONGEST_LINE,CX
  2697.  
  2698. CK_LEN:        INC     CX
  2699.                CMP     SI,DX
  2700.                JNZ     CK_LF
  2701.                CMP     BP,BX
  2702.                JZ      STORE_LEN
  2703.  
  2704. CK_LF:         CMP     BYTE PTR [SI],LF
  2705.                JNZ     CK_CTRL_Z
  2706.                INC     CX
  2707.                INC     SI
  2708.  
  2709. CK_CTRL_Z:     CMP     SI,DX
  2710.                JNZ     CK_CTRL
  2711.                CMP     BP,BX
  2712.                JZ      STORE_LEN
  2713.  
  2714. CK_CTRL:       CMP     BYTE PTR [SI],CTRL_Z
  2715.                JNZ     STORE_LEN
  2716.                INC     CX
  2717.                INC     SI
  2718.  
  2719. STORE_LEN:     MOV     ES:LINE_LEN[DI],CX
  2720.  
  2721.                ADD     DI,SIZE INDEX_REC
  2722.                JBE     TOO_MANY
  2723.                JMP     NEXT_INDEX
  2724. TOO_MANY:      MOV     SI,OFFSET TOO_MANY_LINES
  2725.                STC
  2726.  
  2727. INDEX_END:     POP     ES
  2728.                POP     DS
  2729.                MOV     LAST_LINE,DI
  2730.                RET
  2731.  
  2732. ;----------------------------------------------;
  2733.  
  2734. VIDEO_SETUP:   PUSH    ES
  2735.                MOV     AX,500H                 ;Make sure active page is zero.
  2736.                INT     10H
  2737.                MOV     AX,40H                  ;Point to the ROM BIOS data area
  2738.                MOV     ES,AX
  2739.                MOV     AX,ES:CRT_COLS
  2740.                MOV     COLUMNS,AX
  2741.                SHL     AX,1
  2742.                MOV     CRT_WIDTH,AX
  2743.                MOV     AX,ES:[4EH]
  2744.                MOV     CRT_START,AX
  2745.  
  2746.                MOV     AX,ES:[63H]
  2747.                ADD     AX,6
  2748.                MOV     CX,0B000H
  2749.                CMP     AX,3BAH
  2750.                JZ      STORE_SEG
  2751.                ADD     CX,800H
  2752. STORE_SEG:     MOV     STATUS_REG,AX
  2753.                MOV     VIDEO_SEG,CX
  2754.  
  2755.                MOV     SI,OFFSET MONO_ATTR
  2756.                MOV     AL,ES:CRT_MODE          ;Retrieve current video mode.
  2757.                CMP     AL,7                    ;Is it mono mode?
  2758.                JZ      GET_ROWS                ;If yes, continue.
  2759.                CMP     AL,2                    ;Is it BW80?
  2760.                JZ      GET_ROWS                ;If yes, continue.
  2761.                MOV     SI,OFFSET COLOR_ATTR
  2762.                CMP     AL,3                    ;Is it mode CO80?
  2763.                JZ      GET_ROWS                ;If yes, continue.
  2764.                MOV     AX,3                    ;Else, change video mode to CO80.
  2765.                INT     10H
  2766.  
  2767. GET_ROWS:      XOR     BH,BH
  2768.                MOV     DL,24
  2769.                MOV     AX,1130H
  2770.                INT     10H
  2771.                MOV     ROWS,DL                 ;Store rows.
  2772.                SUB     DL,2
  2773.                XOR     DH,DH
  2774.                MOV     LISTING_LEN,DX
  2775.  
  2776.                POP     ES
  2777.                MOV     DI,OFFSET COLOR
  2778.                MOV     CX,SIZE COLOR_ATTRIBS
  2779.                REP     MOVSB
  2780.  
  2781. ;----------------------------------------------;
  2782.  
  2783. DISPLAY_SETUP: CALL    CLS                     ;Clear screen.
  2784.  
  2785.                CMP     BORDER_FLAG,1
  2786.                JZ      DO_COPYRIGHT
  2787.                MOV     BL,COLOR.W              ;Turn on border.
  2788.                AND     BL,7
  2789.                XOR     BH,BH
  2790.                MOV     AH,0BH
  2791.                INT     10H
  2792.  
  2793. DO_COPYRIGHT:  XOR     AX,AX
  2794.                CALL    CALC_ADDR
  2795.                INC     DI
  2796.                INC     DI
  2797.                MOV     SI,OFFSET COPYRIGHT     ;Point to copyright message.
  2798.                MOV     BH,COLOR.B              ;Use header attribute.
  2799.                CALL    WRITE_STRING            ;And display it.
  2800.                MOV     AL,BOX
  2801.                CALL    WRITE_SCREEN
  2802.                MOV     AL,SPACE
  2803.                CALL    WRITE_SCREEN
  2804.                INC     SI                      ;Bump pointer past LF
  2805.                CALL    WRITE_STRING            ; and display rest of header.
  2806.                RET
  2807.  
  2808. ;----------------------------------------------;
  2809. DISPLAY_MENU:  CALL    MENU_OFFSET
  2810.                PUSH    DI
  2811.                MOV     BH,COLOR.B
  2812.  
  2813.                MOV     SI,OFFSET MENU
  2814.                CALL    WRITE_STRING
  2815.                MOV     AL,LINES_PER_REC
  2816.                ADD     AL,"1"
  2817.                CALL    WRITE_SCREEN
  2818.  
  2819.                CALL    WRITE_STRING
  2820.                MOV     AL,CURRENT_KEY
  2821.                ADD     AL,"1"
  2822.                CALL    WRITE_SCREEN
  2823.  
  2824.                CALL    GET_PRIORITY
  2825.  
  2826.                CALL    WRITE_STRING
  2827.                MOV     CX,SI
  2828.                CALL    DISP_ASCEND
  2829.                MOV     SI,CX
  2830.  
  2831. ;---------------
  2832.  
  2833.                POP     DI
  2834.                ADD     DI,CRT_WIDTH
  2835.                CALL    WRITE_STRING
  2836.                MOV     CX,SI
  2837.                CALL    DISP_ALPHA
  2838.                MOV     SI,CX
  2839.  
  2840.                CALL    WRITE_STRING
  2841.  
  2842.                CALL    DISP_TYPE
  2843.  
  2844.                MOV     SI,OFFSET BLOCK_START
  2845.                CMP     CL,BLOCK_TYPE
  2846.                JZ      DISP_F10
  2847.  
  2848.                MOV     SI,OFFSET LINE_POS_MSG
  2849.                CMP     CL,LINE_TYPE
  2850.                JZ      DISP_F10
  2851.  
  2852.                MOV     SI,OFFSET SPACES
  2853.                CMP     CL,WORD_TYPE
  2854.                JNZ     DISP_F10
  2855.                MOV     SI,OFFSET WORD_POS_MSG
  2856.                CALL    WRITE_STRING
  2857.                CALL    DISP_WORD
  2858.  
  2859. DISP_F10:      CALL    WRITE_STRING
  2860.  
  2861.                MOV     SI,OFFSET ESC_MSG
  2862.                CALL    WRITE_STRING
  2863.                RET
  2864.  
  2865. ;----------------
  2866.  
  2867. DISP_TYPE:     MOV     SI,OFFSET FIELD_OFFSET
  2868.                MOV     CL,KEYS.KEY_FIELD[BP]
  2869.                XOR     CH,CH
  2870.                ADD     SI,CX
  2871.                ADD     SI,CX
  2872.                MOV     SI,[SI]
  2873.                CALL    WRITE_STRING
  2874.                RET
  2875.  
  2876.  
  2877. DISP_ASCEND:   MOV     SI,OFFSET ASCENDING
  2878.                CMP     KEYS.SORT_DIRECTION[BP],ASCEND
  2879.                JZ      DISP_DIR
  2880.                MOV     SI,OFFSET DESCENDING
  2881. DISP_DIR:      CALL    WRITE_STRING
  2882.                RET
  2883.  
  2884.  
  2885. DISP_ALPHA:    MOV     SI,OFFSET ALPHANUMERIC
  2886.                CMP     KEYS.KEY_TYPE[BP],ALPHA_TYPE
  2887.                JZ      DISP_KEY_TYPE
  2888.                MOV     SI,OFFSET NUMERIC
  2889. DISP_KEY_TYPE: CALL    WRITE_STRING
  2890.                RET
  2891.  
  2892.  
  2893. DISP_WORD:     MOV     CL,KEYS.WORD_POS[BP]
  2894.                MOV     AL,"+"
  2895.                OR      CL,CL
  2896.                JNS     DISP_SIGN
  2897.                MOV     AL,"-"
  2898.                NEG     CL
  2899. DISP_SIGN:     CALL    WRITE_SCREEN
  2900.                MOV     AL,CL
  2901.                ADD     AL,"1" - 1
  2902.                CALL    WRITE_SCREEN
  2903.                RET
  2904.  
  2905.  
  2906. DISP_LINE:     MOV     AX,KEYS.LINE_INDEX[BP]
  2907.                PUSH    BX
  2908.                CALL    CALC_ROW
  2909.                POP     BX
  2910.                DIV     CX
  2911.                ADD     AL,"1"
  2912.                CALL    WRITE_SCREEN
  2913.                RET
  2914.  
  2915.  
  2916. DISP_BLOCK:    MOV     AX,KEYS.BLOCK_BEG[BP]
  2917.                INC     AX
  2918.                JZ      DISP_BLOCK_END
  2919.                PUSH    DI
  2920.                CALL    DEC_OUTPUT
  2921.                POP     DI
  2922.                ADD     DI,2 * 5
  2923.                PUSH    DI
  2924.                MOV     AX,KEYS.BLOCK_LEN[BP]
  2925.                CALL    DEC_OUTPUT
  2926.                POP     DI
  2927.                ADD     DI,2 * 5
  2928.                MOV     AX,KEYS.BLOCK_INDEX[BP]
  2929.                PUSH    BX
  2930.                CALL    CALC_ROW
  2931.                POP     BX
  2932.                DIV     CX
  2933.                ADD     AL,"1"
  2934.                CALL    WRITE_SCREEN
  2935. DISP_BLOCK_END:RET
  2936.  
  2937. ;-------------------------------------;
  2938. ;  INPUT: AX = number.
  2939.  
  2940. DEC_OUTPUT:    MOV     SI,10                   ;Convert to decimal.
  2941.                XOR     CX,CX                   ;Zero in counter.
  2942. NEXT_COUNT:    XOR     DX,DX
  2943.                DIV     SI
  2944.                ADD     DL,'0'                  ;Convert to ASCII.
  2945.                PUSH    DX                      ;Save results.
  2946.                INC     CX                      ;Also increment count.
  2947.                CMP     AX,0                    ;Are we done?
  2948.                JNZ     NEXT_COUNT
  2949.  
  2950. NEXT_NUMBER:   POP     AX                      ;Retrieve numbers.
  2951.                CALL    WRITE_SCREEN            ;And write them.
  2952.                LOOP    NEXT_NUMBER
  2953.                RET
  2954.  
  2955. ;-----------------
  2956.  
  2957. GET_PRIORITY:  PUSH    AX
  2958.                MOV     AL,SIZE SORT_KEY
  2959.                MUL     CURRENT_KEY
  2960.                MOV     BP,AX
  2961.                POP     AX
  2962.                RET
  2963.  
  2964. ;----------------------------------------------;
  2965. ;INPUT: CX=char count; AX=character
  2966. REPEAT_CHAR:   PUSH    AX
  2967.                CALL    WRITE_SCREEN
  2968.                POP     AX
  2969.                LOOP    REPEAT_CHAR
  2970.                RET
  2971.  
  2972.  
  2973. ;----------------------------------------------;
  2974. ; INPUT: AX = Starting line; OUTPUT: DI = Video address.
  2975.  
  2976. CALC_ADDR:     MUL     CRT_WIDTH
  2977.                ADD     AX,CRT_START
  2978.                MOV     DI,AX
  2979.                RET
  2980.  
  2981. ;----------------------------------------------;
  2982. ; INPUT:  AL = character to write;  BH = attribute.
  2983.  
  2984. WRITE_SCREEN:  PUSH    ES
  2985.                MOV     ES,CS:VIDEO_SEG         ;Point to screen segment.
  2986.                MOV     DX,CS:STATUS_REG        ;Retrieve status register.
  2987.                MOV     BL,AL                   ;Store character in BL.
  2988.  
  2989. HORZ_RET:      IN      AL,DX                   ;Get status.
  2990.                RCR     AL,1                    ;Is it low?
  2991.                JC      HORZ_RET                ;If not, wait until it is.
  2992.                CLI                             ;No more interrupts.
  2993.  
  2994. HWAIT:         IN      AL,DX                   ;Get status.
  2995.                RCR     AL,1                    ;Is it high?
  2996.                JNC     HWAIT                   ;If no, wait until it is.
  2997.  
  2998.                MOV     AX,BX                   ;Retrieve character; now it's OK
  2999.                STOSW                           ; to write to screen buffer.
  3000.                STI                             ;Interrupts back on.
  3001.                POP     ES
  3002.                RET                             ;Return
  3003.  
  3004. ;----------------------------------------------;
  3005. ; INPUT:  SI -> to string to display;  DI -> where to display it.
  3006. ;   Entry point is WRITE_STRING.
  3007.  
  3008. WRITE_IT:      CALL    WRITE_SCREEN            ;Write a character.
  3009. WRITE_STRING:  LODSB                           ;Retrieve a character.
  3010.                CMP     AL,CR                   ;Keep writing until a carriage
  3011.                JA      WRITE_IT                ; return or zero encountered.
  3012.                RET
  3013.  
  3014. ;----------------------------------------------;
  3015. CLEAR_MENU:    CALL    MENU_OFFSET             ;Calculate menu screen offset.
  3016.                PUSH    DI
  3017.                MOV     BH,COLOR.B              ;Menu attribute.
  3018.                MOV     CX,CRT_WIDTH            ;Blank out the two lines of menu.
  3019. NEXT_MENU:     MOV     AL,SPACE
  3020.                CALL    WRITE_SCREEN
  3021.                LOOP    NEXT_MENU
  3022.                POP     DI
  3023.                RET
  3024.  
  3025. ;----------------------------------------;
  3026. ; OUTPUT: DI -> Screen offset for menu.  ;
  3027. ;----------------------------------------;
  3028. MENU_OFFSET:   MOV     AL,ROWS
  3029.                DEC     AL
  3030.                XOR     AH,AH
  3031.                CALL    CALC_ADDR
  3032.                RET
  3033.  
  3034. ;----------------------------------------------;
  3035. CLS:           MOV     BH,COLOR.B              ;Normal attribute.
  3036. CLS2:          XOR     CX,CX                   ;Top left corner.
  3037.                MOV     DL,BYTE PTR COLUMNS
  3038.                DEC     DL
  3039.                MOV     DH,ROWS
  3040.                MOV     AX,600H                 ;Scroll active page.
  3041.                PUSH    BP
  3042.                INT     10H
  3043.                POP     BP
  3044.                RET
  3045.  
  3046. ;----------------------------------------------;
  3047. CLOSE_SCREEN:  PUSH    AX
  3048.                CALL    CK_MODIFIED
  3049.                MOV     BH,SCREEN_COLOR
  3050.                CALL    CLS2
  3051.  
  3052.                CMP     BORDER_FLAG,1
  3053.                JZ      PLACE_CURSOR
  3054.                XOR     BX,BX
  3055.                MOV     AH,0BH
  3056.                INT     10H
  3057.  
  3058. PLACE_CURSOR:  XOR     DX,DX
  3059.                CALL    SET_CURSOR
  3060.                POP     AX
  3061.                RET
  3062.  
  3063. ;----------------------------------------------;
  3064. BEEP:          MOV     BX,NOTE                 ;Tone frequency divisor.
  3065.                MOV     DX,12H
  3066.                XOR     AX,AX
  3067.                DIV     BX
  3068.                MOV     BX,AX                   ;8253 countdown.
  3069.  
  3070.                CALL    DELAY                   ;Wait till clock rolls over.
  3071.  
  3072.                MOV     AL,0B6H                 ;Channel 2 speaker functions.
  3073.                OUT     43H,AL                  ;8253 Mode Control.
  3074.                JMP     $+2                     ;IO delay.
  3075.                MOV     AX,BX                   ;Retrieve countdown.
  3076.                OUT     42H,AL                  ;Channel 2 LSB.
  3077.                JMP     $+2
  3078.                MOV     AL,AH                   ;Channel 2 MSB.
  3079.                OUT     42H,AL
  3080.                IN      AL,61H                  ;Port B.
  3081.                OR      AL,3                    ;Turn on speaker.
  3082.                JMP     $+2
  3083.                OUT     61H,AL
  3084.  
  3085.                CALL    DELAY                   ;Delay one second.
  3086.                IN      AL,61H                  ;Get Port B again.
  3087.                AND     AL,NOT 3                ;Turn speaker off.
  3088.                JMP     $+2
  3089.                OUT     61H,AL
  3090.                RET                             ;Done.
  3091.  
  3092. ;-----------------------------;
  3093. DELAY:         PUSH    DS                      ;Preserve data segment.
  3094.                MOV     AX,40H                  ;Point to BIOS data segment.
  3095.                MOV     DS,AX
  3096.                MOV     AX,DS:[6CH]             ;Retrieve timer low.
  3097. NEXT_BEEP:     MOV     DX,DS:[6CH]             ;Retrieve timer low.
  3098.                CMP     DX,AX                   ;Have we timed out?
  3099.                JZ      NEXT_BEEP               ;If not, wait until second up.
  3100.                POP     DS                      ;Restore data segment.
  3101.                RET
  3102.  
  3103. ;*************LINE EDITOR**********************;
  3104.  
  3105. LINE_START     DW      ?
  3106. LINE_END       DW      ?
  3107.  
  3108. ;INPUT: DI=buffer position; LINE_START, LINE_END.
  3109. ;OUTPUT: AL=char. AH=scan code. CY=1 if Esc pressed.
  3110.  
  3111. EDITOR:        CALL    GETKEY
  3112.                XCHG    AL,AH
  3113.                JNC     DO_EDIT
  3114.                JMP     EDITOR_END
  3115. DO_EDIT:       MOV     BX,DI
  3116.                MOV     DX,LINE_START
  3117.                MOV     CX,LINE_END
  3118.  
  3119.                CMP     AH,ENTER_SCAN
  3120.                JNZ     CK_RIGHT
  3121.                JMP     EDITOR_DONE
  3122.  
  3123. CK_RIGHT:      CMP     AX,RIGHT_SCAN SHL 8
  3124.                JNZ     CK_LEFT
  3125.                CMP     DI,CX
  3126.                JZ      EDITOR_DONE
  3127.                CMP     BYTE PTR [DI],SPACE
  3128.                JZ      EDITOR_DONE
  3129.                INC     DI
  3130.  
  3131. CK_LEFT:       CMP     AX,LEFT_SCAN SHL 8
  3132.                JNZ     CK_BS
  3133.                CMP     DI,DX
  3134.                JZ      EDITOR_DONE
  3135.                DEC     DI
  3136.  
  3137. CK_BS:         CMP     AH,BS_SCAN
  3138.                JNZ     CK_DEL
  3139.                CMP     DI,DX
  3140.                JZ      EDITOR_DONE
  3141.                DEC     DI
  3142.                CALL    CK_INSERT
  3143.                JNZ     DO_DEL
  3144.                MOV     BYTE PTR [DI],SPACE
  3145.                JMP     SHORT EDITOR_CHANGE
  3146.  
  3147. CK_DEL:        CMP     AX,DEL_SCAN SHL 8
  3148.                JNZ     CK_HOME
  3149. DO_DEL:        PUSH    DI
  3150.                MOV     SI,DI
  3151.                INC     SI
  3152.                DEC     CX
  3153.                SUB     CX,DI
  3154.                JS      DEL_END
  3155.                REP     MOVSB
  3156.                MOV     BYTE PTR [DI],SPACE
  3157. DEL_END:       POP     DI
  3158.                JMP     SHORT EDITOR_CHANGE
  3159.  
  3160. CK_HOME:       CMP     AX,HOME_SCAN SHL 8
  3161.                JNZ     CK_END2
  3162.                MOV     DI,DX
  3163.  
  3164. CK_END2:       CMP     AX,END_SCAN SHL 8
  3165.                JNZ     CK_ASCII
  3166. NEXT_CK_END2:  CMP     DI,CX
  3167.                JZ      EDITOR_DONE
  3168.                CMP     BYTE PTR [DI],SPACE
  3169.                JZ      EDITOR_DONE
  3170.                INC     DI
  3171.                JMP     NEXT_CK_END2
  3172.  
  3173. CK_ASCII:      CMP     AL,SPACE
  3174.                JB      EDITOR_DONE
  3175.                CMP     AL,127
  3176.                JA      EDITOR_DONE
  3177.                CMP     DI,LINE_END
  3178.                JAE     EDITOR_DONE
  3179.                CALL    CK_INSERT
  3180.                JNZ     DO_INSERT
  3181.                JMP     SHORT EDITOR_DONE1
  3182.  
  3183. DO_INSERT:     PUSH    DI
  3184.                DEC     CX
  3185.                MOV     DI,CX
  3186.                SUB     CX,BX
  3187.                JZ      EDITOR_DONE2
  3188.                MOV     SI,DI
  3189.                DEC     SI
  3190.                STD
  3191.                REP     MOVSB
  3192.                CLD
  3193. EDITOR_DONE2:  POP     DI
  3194. EDITOR_DONE1:  STOSB
  3195.  
  3196. EDITOR_CHANGE: ; MOV     MODIFY_FLAG,1
  3197. EDITOR_DONE:   CLC
  3198. EDITOR_END:    RET
  3199.  
  3200. ;--------------------------
  3201.  
  3202. CK_INSERT:     PUSH    DS
  3203.                MOV     DX,40H
  3204.                MOV     DS,DX
  3205.                MOV     DL,DS:[17H]
  3206.                TEST    DL,80H                  ;Insert
  3207.                POP     DS
  3208.                RET
  3209.  
  3210. ;----------------------------------------------;
  3211.  
  3212. DOS_CURSOR:    MOV     DX,200H                 ;Put cursor on screen in case
  3213.                JMP     SHORT SET_CURSOR        ; of critical error like drive
  3214.                                                ; drive door open.
  3215.  
  3216. HIDE_CURSOR:   MOV     DH,ROWS                 ;Retrieve CRT rows.
  3217.                INC     DH                      ;Move one line below off screen.
  3218.                XOR     DL,DL                   ;Column zero.
  3219.  
  3220. SET_CURSOR:    PUSH    BX
  3221.                XOR     BH,BH                   ;Page zero.
  3222.                MOV     AH,2                    ;Set cursor position.
  3223.                INT     10H
  3224.                POP     BX
  3225.                RET
  3226.  
  3227. ;----------------------------------------------;
  3228. ; INPUT:  DI -> Valid scan codes table; CX = Length of table
  3229. ; OUTPUT: AL=Scan code; AH=Char; CF=1 if Esc pressed.
  3230.  
  3231. DISPATCH:      CALL    GETKEY
  3232.                PUSH    AX
  3233.                JC      DISPATCH_END
  3234.                CMP     AH,CR
  3235.                JZ      DISPATCH_END
  3236.                MOV     BX,CX
  3237.                MOV     DX,DI
  3238.                ADD     DX,CX
  3239.                REPNZ   SCASB
  3240.                JNZ     NO_DISPATCH
  3241.  
  3242. GOT_DISPATCH:  SUB     BX,CX
  3243.                DEC     BX
  3244.                SHL     BX,1
  3245.                ADD     BX,DX
  3246.                CALL    GET_PARAMS
  3247. DO_DISPATCH:   CALL    [BX]                    ;Process the command.
  3248. NO_DISPATCH:   CLC
  3249. DISPATCH_END:  POP     AX
  3250.                RET
  3251.  
  3252. ;----------------------------------------------;
  3253.  
  3254. GET_PARAMS:    MOV     DI,TOP_LINE
  3255.                MOV     CX,SIZE INDEX_REC
  3256.                MOV     AX,LISTING_LEN
  3257.                DEC     AX
  3258.                MUL     CL
  3259.                MOV     SI,AX
  3260.                ADD     SI,DI
  3261.                CMP     SI,LAST_LINE
  3262.                JBE     CALC_LINE
  3263.                MOV     SI,LAST_LINE
  3264. CALC_LINE:     MOV     AX,SI
  3265.                SUB     AX,DI
  3266.                DIV     CL
  3267.                XOR     AH,AH
  3268.                MOV     DX,AX
  3269.                RET
  3270.  
  3271. ;----------------------------------------------;
  3272.  
  3273. GETKEY:        MOV     AH,0                    ;Wait for next keyboard input.
  3274.                INT     16H
  3275.                XCHG    AH,AL
  3276.                CMP     AL,ESC_SCAN
  3277.                STC
  3278.                JZ      GETKEY_END
  3279.                CLC
  3280. GETKEY_END:    RET
  3281.  
  3282. CK_KEY:        MOV     AH,1                    ;Is there a keystroke available.
  3283.                INT     16H
  3284.                RET
  3285.  
  3286. CLEAR_IT:      CALL    GETKEY                  ;Read keystrokes until buffer
  3287. CLEAR_KEY:     CALL    CK_KEY                  ; empty.
  3288.                JNZ     CLEAR_IT
  3289.                RET
  3290.  
  3291. ;----------------------------------------------;
  3292.  
  3293. WRITE_TTY:     MOV     AH,0EH
  3294.                INT     10H
  3295.                RET
  3296.  
  3297. ;----------------------------------------------;
  3298.  
  3299. PRINT_STRING:  MOV     AH,9                    ;Print string via DOS.
  3300.                INT     21H
  3301.                RET
  3302.  
  3303. ;----------------------------------------------;
  3304.  
  3305. EVEN
  3306. STACK_POINTER  =       $ + 256
  3307.  
  3308.  
  3309. _TEXT          ENDS
  3310.                END     START
  3311.